移动 StorageFile

问题描述

序言:

我正在为 UWP 编写 sqlite GUI 客户端。我将 Microsoft.Data.sqlite 库用于 sqlite API 和 C#。此外,我使用重定向表能够在 Microsoft Store 中发布的沙盒应用程序中打开数据库重定向表将 CreateFileW 替换为 CreateFileFromAppW 调用等。

问题:

用户具有 File -> Save as 功能。当用户创建一个新的数据库文件时,会在 app 本地目录中创建。接下来,当用户 saves 他/她的数据库 as 我需要移动这个文件。我使用 StorageFile API 因为我不能在沙盒应用程序中使用任何其他文件 API。所以我打电话:

var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("sqlite3 Database",new List<string>() { ".sqlite",".db" });
savePicker.SuggestedFileName = "Database";
var file = await savePicker.PickSaveFileAsync();
if(null != file)
{                    
    Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file);
    sqliteConnection.Close();  // it is important cause if I skip this moving a file will fail
    var localFolder = ApplicationData.Current.LocalFolder;
    var currentStorageFile = await localFolder.GetFileAsync(App.UnsavedDatabaseFileName);  // here I obtain StorageFile for opened database
    await currentStorageFile.MoveAndReplaceAsync(file);  // here I move a file
    sqliteConnection = new sqliteConnection("Data Source=" + file.Path);
    sqliteConnection.open();  // this line fails with error 14: cannot open database file
}            

我也尝试跳过关闭和重新打开连接 -> 然后移动文件失败。 如果我在 fileopenpickerawait currentStorageFile.MoveAndReplaceAsync(file); 之间调用 sqliteConnection = new sqliteConnection("Data Source=" + file.Path); 则一切正常,但是在文件保存选择器之后显示文件打开选择器是非常糟糕的用户体验。我知道沙盒应用程序仅在用户手动选择文件后才授予文件访问权限。但看起来 FileSavePicker 不像 fileopenpicker 那样给我权限。我找不到有关它的任何信息。

尾声:

这是应用程序 https://sqliteman.dev。请随时批评,因为它使我的应用程序变得更好。

解决方法

如果是权限问题,那么一种解决方案是在应用的清单中声明 BroadFileSystemAccess。

https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions

我觉得奇怪的是,您对自己创建的文件没有写权限。

,

尝试将 MoveAndReplaceAsync() 放在 using 语句中,并在其外部打开 SQLite 连接。

,

更新:

我已经使用了 BroadFileSystemAccess 功能进行了测试,但它不起作用并且仍然报告“无法打开数据库文件”的异常。因此,使用广泛的文件系统访问能力是不可行的。

如果你想在uwp中使用Sqlite,只有两个位置可以访问。 ApplicationData和Application安装目录,区别在于ApplicationInstallation只能读取,ApplicationData可以读写。所以当你连接位于另一个位置的文件时,它报告了异常。

我的意思是你可以把数据库文件存放在任何地方,但是当你操作这个数据库文件时,你需要把这个文件移动到可以访问的位置。(ApplicationData,Application install directory)。否则无法向数据库文件表中插入数据,甚至无法连接数据库文件。