2017-02-02 1 views
0

Ich habe gekämpft, um eine Möglichkeit zum Fortbestehen einer SQLite-Datenbank auf einem Pi unter Win IoT zu finden, auf die von verschiedenen Hintergrundanwendungen (nicht gleichzeitig) zugegriffen werden kann.SQLite.Net wird nicht in Win IoT-Bibliothek erstellen

Ich dachte, ich hätte die Antwort, als ich Bibliotheken entdeckte (Musik, Bilder, Videos - aber pervers keine Dokumente, ohne mehr Arbeit). Ich kann eine Textdatei in einer App erstellen und sie in den Standardordner der Bilderbibliothek schreiben. Ich kann dann die Textdatei mit einer anderen App lesen. File.Exists gibt true zurück. Bingo (dachte ich)!

SQLite wird jedoch keine Datenbank im Ordner erstellen oder eine vorhandene Datenbank öffnen, die ich in den Ordner kopiere. SQLite.Net.SQLiteConnection gibt eine SQLite-Ausnahme zurück: "Datenbankdatei konnte nicht geöffnet werden: C: \ Data \ Users \ DefaultAccount \ Pictures \ MyDb.db (CannotOpen)" - keine weiteren Hinweise.

Der Ordner scheint vollständige Berechtigungen zu erteilen. Hat jemand irgendwelche Ideen, bitte?

Erstellen und Schreiben einer Textdatei:

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}"); } 
     } 
    } 
} 

Produziert:

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

Reading:

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}"); } 
     } 
    } 
} 

Produziert:

'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 
+0

Die Ausnahme aufgrund der Zugriffsbeschränkung auf den Pfad "C: \ Data \ Users \ DefaultAccount \ Pictures \" der UWP-App. Sie können [Dateizugriffsrechte] (https://msdn.microsoft.com/en-us/windows/uwp/files/file-access-permissions) überprüfen. –

+0

Danke für Ihre Antwort, Rita. Es ist jedoch merkwürdig, dass ich eine Textdatei in diesem Ordner erstellen und lesen konnte, indem ich Standard-SYSTEM.IO-Stream-Methoden verwendete. Außerdem könnte ich eine Datei in den Ordner kopieren und die Datei vom Windows Explorer auf meinem PC öffnen (der mir als Benutzer auf dem Pi volle Privilegien meldet). Ich hätte nicht gedacht, dass SQLite größere Berechtigungen benötigen würde als das Lesen und Schreiben für diese anderen Operationen. – David

+0

** "dass ich in der Lage war, eine Textdatei in diesem Ordner unter Verwendung der Standard-SYSTEM.IO-Stream-Methoden zu erstellen und zu lesen." ** Können Sie den Code dieses Teils anzeigen? –

Antwort

2

SQLite wird jedoch keine Datenbank im Ordner erstellen oder eine vorhandene Datenbank öffnen, die ich in den Ordner kopiere. SQLite.Net.SQLiteConnection gibt eine SQLite-Ausnahme zurück: "Konnte nicht Datenbankdatei öffnen: C: \ Data \ Benutzer \ DefaultAccount \ Pictures \ MyDb.db (CannotOpen)" - keine weiteren Hinweise.

Ja, ich reproduziert dieses Problem. Es scheint, dass dieser Ordner nicht mit SQLite-Dateioperationen funktioniert, aber ich weiß nicht, wo das Problem liegt.

Als Workaround können Sie PublisherCacheFolder verwenden. Ich erstelle die .db-Datei und schreibe Daten in eine Hintergrund-App. Und lies die Daten von einer anderen Hintergrund-App. Es klappt.

Kontaktklasse:

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

erstellen und Datei schreiben:

  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); 
       } 
      } 

lesen Datei:

  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); 
      } 

Um diesen Verleger Ordner verwenden Sie die folgenden Zeilen in Paket hinzufügen. appxmanifest:

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

Danke, Rita. Hat sehr gut funktioniert. Zum Lesen benutze ich die Async-Version von SqlLite und erstelle die Verbindung wie folgt: – David

0

Danke, Rita. Hat sehr gut funktioniert.Zum Nutzen von jedermann zu lesen, ich habe die Asynchron-Version von SqlLite verwende und die Verbindung wie folgt erstellen:

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; 
    } 

Dann zum Beispiel, lesen Sie eine Tabelle vom Typ Parms:

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

Meine Sorge Über die SQLite-asynchrone Verbindung ist es nicht IDisposable. Wird also der Fabrik irgendwann der Dampf ausgehen (Speicher, Griffe)? Aber ich denke, das ist ein Thema für einen anderen Thread.

Verwandte Themen