diff --git a/src/Microsoft.Data.Sqlite.Core/Properties/Microsoft.Data.Sqlite.rd.xml b/src/Microsoft.Data.Sqlite.Core/Properties/Microsoft.Data.Sqlite.rd.xml new file mode 100644 index 00000000000..4549c8a4ef0 --- /dev/null +++ b/src/Microsoft.Data.Sqlite.Core/Properties/Microsoft.Data.Sqlite.rd.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs new file mode 100644 index 00000000000..5dbef58ccac --- /dev/null +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Reflection; + +namespace Microsoft.Data.Sqlite.Utilities +{ + internal class ApplicationDataHelper + { + private static object _appData; + private static string _localFolder; + private static string _tempFolder; + + public static object CurrentApplicationData + => _appData ??= LoadAppData(); + + public static string TemporaryFolderPath + => _tempFolder ??= GetFolderPath("TemporaryFolder"); + + public static string LocalFolderPath + => _localFolder ??= GetFolderPath("LocalFolder"); + + private static object LoadAppData() + { + try + { + return Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime") + ?.GetRuntimeProperty("Current").GetValue(null); + } + catch + { + // Ignore "The process has no package identity." + return null; + } + } + + private static string GetFolderPath(string propertyName) + { + var appDataType = CurrentApplicationData?.GetType(); + var temporaryFolder = appDataType?.GetRuntimeProperty(propertyName).GetValue(CurrentApplicationData); + + return temporaryFolder?.GetType().GetRuntimeProperty("Path").GetValue(temporaryFolder) as string; + } + } +} diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs index fb8e0218ef3..2d39d1a78eb 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs @@ -1,26 +1,48 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Reflection; +using static SQLitePCL.raw; + namespace Microsoft.Data.Sqlite.Utilities { internal static class BundleInitializer { + private const int SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1; + private const int SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2; + public static void Initialize() { - Assembly assembly; + Assembly assembly = null; try { assembly = Assembly.Load(new AssemblyName("SQLitePCLRaw.batteries_v2")); } catch { - return; } - assembly.GetType("SQLitePCL.Batteries_V2").GetTypeInfo().GetDeclaredMethod("Init") - .Invoke(null, null); + if (assembly != null) + { + assembly.GetType("SQLitePCL.Batteries_V2").GetTypeInfo().GetDeclaredMethod("Init") + .Invoke(null, null); + } + + if ((!AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue19754", out var isEnabled) || !isEnabled) + && ApplicationDataHelper.CurrentApplicationData != null) + { + var rc = sqlite3_win32_set_directory( + SQLITE_WIN32_DATA_DIRECTORY_TYPE, + ApplicationDataHelper.LocalFolderPath); + SqliteException.ThrowExceptionForRC(rc, db: null); + + rc = sqlite3_win32_set_directory( + SQLITE_WIN32_TEMP_DIRECTORY_TYPE, + ApplicationDataHelper.TemporaryFolderPath); + SqliteException.ThrowExceptionForRC(rc, db: null); + } } } }