移动 StorageFile 后立即在 UWP 中打开 SQLite 连接

Posted

技术标签:

【中文标题】移动 StorageFile 后立即在 UWP 中打开 SQLite 连接【英文标题】:Open SQLite connection in UWP right after moving StorageFile 【发布时间】:2021-08-29 05:24:21 【问题描述】:

序幕:

我正在为 UWP 编写 SQLite GUI 客户端。我将 Microsoft.Data.Sqlite 库用于带有 C# 的 SQLite API。我还使用重定向表来打开我在 Microsoft Store 中发布的沙盒应用程序中的数据库。重定向表将 CreateFileW 替换为 CreateFileFromAppW 调用等。

问题:

用户拥有File -> Save as 功能。当用户创建一个新的数据库文件时,会在应用程序本地目录中创建一个。接下来当用户保存他/她的数据库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
            

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

结语:

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

broadFileSystemAccess 在沙盒应用中不可用。我已经试过了【参考方案2】:

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

【讨论】:

我不确定它是否可以帮助导致StorageFile.MoveAndReplaceAsync 返回IAsyncAction 什么都不做(更多细节在这里docs.microsoft.com/en-us/uwp/api/…)。反正我会试试的 我不能这样做,因为StorageFile.MoveAndReplaceAsync 调用的结果无法保存到变量中【参考方案3】:

更新:

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

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

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

【讨论】:

我按照您的要求修改了Package.appxmanifest,但在Settings &gt; Privacy &gt; File system 中找不到我的应用程序。该列表为空,并且切换按钮 Allow apps to access you FS 处于打开状态。为什么。顺便说一句Settings &gt; Privacy &gt; Videos 列出了三个应用程序:相机、电影和 Xbox-something。为什么我在设置中看不到我的应用? 应用程序需要运行一次,以便下次运行应用程序时可以在设置(设置>隐私>文件系统)中找到该应用程序。 @fnc12 我已经更新了我的答案,请检查一下。另外我想知道你在使用FileOpenPick获取权限时是否可以操作这个数据库文件,比如插入和更新数据。 1) 我确实运行了该应用程序一次甚至更多次,但它没有出现在 Settings &gt; Privacy &gt; File system 中。该列表为空。我还在发布和调试模式下运行了该应用程序。我还删除了从 Microsoft Store 安装的应用程序版本,但这没有帮助。 2)我不明白你的答案更新。这是否意味着用户只能将数据库文件存储在提到的文件夹中?此外,您的 C# 代码 sn-p 看起来很奇怪:您有三个 StorageFile 实例。为什么是三个?只需要其中两个:旧的和新的。但是你有currentStorageFilefilefile1 @fnc12 我已经测试过这个功能并修改了我的答案,你可以检查一下。

以上是关于移动 StorageFile 后立即在 UWP 中打开 SQLite 连接的主要内容,如果未能解决你的问题,请参考以下文章

如何使 StorageFile.DisplayName getter 在 UWP 中系统地排除 FileType

uwp 文件系统上 StorageFile 的唯一标识符

uwp StorageFile 没有得到简单的缩略图

如何设置 UWP C# StorageFile 以将 SoftwareBitmap 存储到特定路径

另一个进程错误正在使用 UWP StorageFile 文件

你可以从它的路径访问一个选择的 StorageFile 吗? - UWP