无法打开数据库文件(误用)SqlLiteAsyncConnection

Lan*_*nce -1 c# sqlite xamarin.forms uwp

尝试打开 SQLite 连接时出现异常“无法打开数据库文件:[路径](误用)”。

我正在创建一个 Xamarin.Forms 应用程序,并在 UWP 中进行调试,这是我收到异常的地方。

我的数据存储类的构造函数创建连接和表:

internal static string DBPath
{
    get
    {
        const string FILE_NAME = "TheRandomizer.db3";
        if (Device.RuntimePlatform == Device.Android)
        {
            return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), FILE_NAME);
        }
        else
        {
             return Path.Combine(ApplicationData.Current.LocalFolder.Path, FILE_NAME);
        }
    }
}

public SqliteDataStore()
{
    _database = new SQLiteAsyncConnection(DBPath, SQLiteOpenFlags.Create);
    // Fails trying to perform this action:
    _database.CreateTableAsync<GeneratorTable>().Wait();
    _database.CreateTableAsync<TagTable>().Wait();
}
Run Code Online (Sandbox Code Playgroud)

完整的源代码可以在我的 GitHub 上查看。

堆栈跟踪:

在 System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken CancellationToken) 在 System.Threading.Tasks.Task.Wait() 在 TheRandomizer.Services.SqliteDataStore..ctor() 在 TheRandomizer.ViewModels.BaseViewModel.get_DataStore()在TheRandomizer.ViewModels.GeneratorListViewModel.ExecuteLoadItemsCommand()

Mar*_*und 5

更新

我已经在本地测试了您的代码,并看到该行为实际上正在发生,经过一些调试后,我认为我可能有两个原因:

首先,构造函数只有标志SQLiteOpenFlags.Create。显然这不会给你任何其他权限,包括读/写。相反,您可以完全省略第二个参数:

_database = new SQLiteAsyncConnection(DBPath);
Run Code Online (Sandbox Code Playgroud)

或者包含显式ReadWrite标志(我还包含了该FullMutex标志,因为建议用于异步连接):

_database = new SQLiteAsyncConnection(
     DBPath, 
     SQLiteOpenFlags.Create | 
     SQLiteOpenFlags.FullMutex | 
     SQLiteOpenFlags.ReadWrite );
Run Code Online (Sandbox Code Playgroud)

在数据库中创建GeneratorTable表时出现第二个问题。SQLite 不知道如何存储该Version属性,因为它是自定义GeneratorVersion类型。因此,您可能必须将其分解为简单的属性或添加一个[Ignore]属性。

原答案

我检查了您的源代码,发现您正在尝试将数据库存储在Environment.SpecialFolder.Personal文件夹中。对于 UWP,这实际上解析为C:\Users\$Username$\Documents,UWP 应用程序无权访问它,因为它在沙箱中运行并且无权访问。

相反,您必须使用应用程序的数据文件夹(您可能实际上打算这样做):

Path.Combine(ApplicationData.Current.LocalFolder.Path, FILE_NAME);
Run Code Online (Sandbox Code Playgroud)