【问题标题】:SQLite.Net Won't Create In Win IoT LibrarySQLite.Net 不会在 Win IoT 库中创建
【发布时间】:2017-02-02 17:49:06
【问题描述】:

我一直在努力寻找一种在 Win IoT 下的 Pi 上持久化 SQLite 数据库的方法,该数据库可以被不同的后台应用程序访问(不能同时访问)。

当我发现图书馆(音乐、图片、视频 - 但反常地不是文档,没有更多工作)时,我以为我已经找到了答案。我可以在一个应用程序中创建一个文本文件并将其写入图片库的默认文件夹。然后我可以用另一个应用程序读取文本文件。 File.Exists 返回真。宾果游戏(我想)!

但是,SQLite 不会在文件夹中创建数据库,也不会打开我复制到文件夹中的现有数据库。 SQLite.Net.SQLiteConnection 返回 SQLite 异常:“无法打开数据库文件:C:\Data\Users\DefaultAccount\Pictures\MyDb.db (CannotOpen)”——没有进一步的线索。

该文件夹似乎授予完全权限。请问大家有什么想法吗?

创建和编写文本文件:

using System;
using Windows.ApplicationModel.Background;
using System.IO;
using System.Diagnostics;

//*** NOTE: Pictures Library checked in Package.appxmanifest 'Capabilities'

namespace LibraryTest
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral Deferral;

        public async void Run (IBackgroundTaskInstance taskInstance)
        {
            Deferral = taskInstance.GetDeferral ();

            var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync
                (Windows.Storage.KnownLibraryId.Pictures);

            string path = myPictures.SaveFolder.Path;
            Debug.WriteLine ($"'Pictures' Folder: {path}");

            string newFilePath = Path.Combine (path, "TestTextFile.txt");
            Debug.WriteLine ($"New File Path: {newFilePath}");

            try {
                using ( var stream = File.OpenWrite (newFilePath) ) {
                    using ( var writer = new StreamWriter (stream) ) {
                        writer.Write ("This is some test text.");
                    }
                }
                Debug.WriteLine ($"File created OK");
            }
            catch (Exception ex) { Debug.WriteLine ($"Exception: {ex.Message}"); }
        }
    }
}

制作:

'Pictures' Folder: C:\Data\Users\DefaultAccount\Pictures
New File Path: C:\Data\Users\DefaultAccount\Pictures\TestTextFile.txt
File created OK

阅读:

using System;
using Windows.ApplicationModel.Background;
using System.IO;
using System.Diagnostics;

//*** NOTE: Pictures Library checked in Package.appxmanifest 'Capabilities'

namespace ReadLibraryTest
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral Deferral;

        public async void Run (IBackgroundTaskInstance taskInstance)
        {
            Deferral = taskInstance.GetDeferral ();

            var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync
                (Windows.Storage.KnownLibraryId.Pictures);

            string path = myPictures.SaveFolder.Path;
            Debug.WriteLine ($"'Pictures' Folder: {path}");

            string newFilePath = Path.Combine (path, "TestTextFile.txt");
            Debug.WriteLine ($"New File Path: {newFilePath}");

            try {
                using ( var stream = File.OpenRead (newFilePath) ) {
                    using ( var reader = new StreamReader (stream) ) {
                        string fileContents = reader.ReadLine ();
                        Debug.WriteLine ($"First line of file: '{fileContents}'");
                    }
                }
                Debug.WriteLine ($"File read OK");
            }
            catch ( Exception ex ) { Debug.WriteLine ($"Exception: {ex.Message}"); }
        }
    }
}

制作:

'Pictures' Folder: C:\Data\Users\DefaultAccount\Pictures
New File Path: C:\Data\Users\DefaultAccount\Pictures\TestTextFile.txt
First line of file: 'This is some test text.'
File read OK

【问题讨论】:

  • UWP 应用的路径“C:\Data\Users\DefaultAccount\Pictures\”访问限制导致的异常。您可以查看File access permissions
  • 感谢您的回复,丽塔。不过,奇怪的是,我能够使用标准 SYSTEM.IO 流方法在此文件夹中创建和读取文本文件。此外,我可以将一个文件复制到该文件夹​​中,然后从我的 PC 上的 Windows 资源管理器中打开该文件(它向作为 Pi 用户的我报告完全权限)。我不会想到 SQLite 需要比这些其他操作允许的读写权限更大的权限。
  • “我能够使用标准 SYSTEM.IO 流方法在此文件夹中创建和读取文本文件。” 你能显示这部分的代码吗?
  • 丽塔,我已将代码添加到上面的原始问题中。新文件在 Windows 资源管理器中可见。

标签: c# iot raspberry-pi3 sqlite-net windowsiot


【解决方案1】:

但是,SQLite 不会在文件夹中创建数据库或打开一个 我复制到文件夹的现有数据库。 SQLite.Net.SQLiteConnection 返回一个 SQLite 异常:“不能 打开数据库文件:C:\Data\Users\DefaultAccount\Pictures\MyDb.db (CannotOpen)" - 没有更多线索。

是的,我复制了这个问题。看来这个文件夹不适用于 SQLite 文件操作,但我不知道问题出在哪里。

作为一种解决方法,您可以使用PublisherCacheFolder。我创建 .db 文件并在一个后台应用程序中写入数据。并从另一个后台应用程序读取数据。有用。

联系人类:

public sealed class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
}

创建和写入文件:

            StorageFolder sharedFonts = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test");

            var sqlpath = System.IO.Path.Combine(sharedFonts.Path, "MyDb.db");

            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqlpath))
            {
                conn.CreateTable<Contact>();
                for (var i = 0; i < 100; i++)
                {
                    Contact contact = new Contact()
                    {
                        Id = i,
                        Name = "A"
                    };
                    conn.Insert(contact);
                }
            }

读取文件:

            StorageFolder sharedFonts = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test");

            var sqlpath = System.IO.Path.Combine(sharedFonts.Path, "MyDb.db");

            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqlpath))
            {
                var query = conn.Table<Contact>().Where(v => v.Name.Equals("A"));

                foreach (var stock in query)
                    Debug.WriteLine("contact: " + stock.Id);
            }

要使用此发布者文件夹,您需要在 Package.appxmanifest 中添加以下行:

  <Extensions>
    <Extension Category="windows.publisherCacheFolders">
      <PublisherCacheFolders>
        <Folder Name="test" />
      </PublisherCacheFolders>
    </Extension>
  </Extensions>

【讨论】:

  • 谢谢,丽塔。工作得很好。为了方便阅读,我使用的是异步版本的 SqlLite 并按如下方式创建连接:
【解决方案2】:

谢谢,丽塔。工作得很好。为了方便阅读,我使用的是异步版本的 SqlLite 并按如下方式创建连接:

const string FileName = "MyFile.db";
string DbDir;
string DbPath;


Constructor:
    DbDir = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test").Path;
    DbPath = Path.Combine (DbDir, DbFileName);


public SQLite.Net.Async.SQLiteAsyncConnection GetConnectionAsync ()
    {
        var connectionFactory = new Func<SQLite.Net.SQLiteConnectionWithLock>(()=>
                new SQLite.Net.SQLiteConnectionWithLock(new SQLitePlatformWinRT(),
                        new SQLite.Net.SQLiteConnectionString(DbPath, storeDateTimeAsTicks: false)));
        var asyncConnection = new SQLiteAsyncConnection(connectionFactory);
        return asyncConnection;
    }

然后,例如,读取 Parms 类型的表:

public async Task<Parms> ReadParmsAsync ()
{
    var db = GetConnectionAsync ();
    var query = db.Table<Parms> ().Where (p => p.Id == 1);
    return await query.FirstOrDefaultAsync ();
}

我对 SQLite 异步连接的担忧是它不是 IDisposable。因此,“工厂”最终会耗尽动力(内存、句柄)吗?但我想这是另一个主题的主题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 2023-03-22
    • 2019-04-26
    相关资源
    最近更新 更多