Freigeben über


Lokale .NET MAUI-Datenbanken

Browse sample. Durchsuchen des Beispiels

Das SQLite-Datenbankmodul ermöglicht .NET Multi-Platform App UI (.NET MAUI)-Apps das Laden und Speichern von Datenobjekten in freigegebenem Code. Sie können SQLite.NET in .NET MAUI-Apps integrieren, um Informationen in einer lokalen Datenbank zu speichern und abzurufen, indem Sie die folgenden Schritte ausführen:

  1. Installieren Sie das NuGet-Paket.
  2. Konfigurieren Sie Konstanten.
  3. Erstellen Sie eine Datenbankzugriffsklasse.
  4. Zugreifen auf Daten.
  5. Erweiterte Konfiguration

In diesem Artikel wird das sqlite-net-pcl NuGet-Paket verwendet, um SQLite-Datenbankzugriff auf eine Tabelle zum Speichern von Todoelementen bereitzustellen. Eine Alternative besteht darin, das Microsoft.Data.Sqlite NuGet-Paket zu verwenden, bei dem es sich um einen einfachen ADO.NET Anbieter für SQLite handelt. Microsoft.Data.Sqlite implementiert die allgemeinen ADO.NET Abstraktionen für Funktionen wie Verbindungen, Befehle und Datenleseprogramme.

Installieren des SQLite NuGet-Pakets

Verwenden Sie den NuGet-Paket-Manager, um nach dem sqlite-net-pcl-Paket zu suchen und die neueste Version zu Ihrem .NET MAUI-App-Projekt hinzuzufügen.

Es gibt eine Reihe von NuGet-Paketen mit ähnlichen Namen. Das richtige Paket verfügt über die folgenden Attribute:

  • ID: sqlite-net-pcl
  • Ersteller: SQLite-net
  • Besitzer: praeclarum
  • NuGet-Link:sqlite-net-pcl

Verwenden Sie trotz des Paketnamens das sqlite-net-pcl NuGet-Paket in .NET MAUI-Projekten.

Wichtig

SQLite.NET ist eine Drittanbieterbibliothek, die vom praeclarum/sqlite-net-Repository unterstützt wird.

Installieren von SQLitePCLRaw.bundle_green

Zusätzlich zu sqlite-net-pcl müssen Sie vorübergehend die zugrunde liegende Abhängigkeit installieren, die SQLite auf jeder Plattform verfügbar macht:

Konfigurieren von App-Konstanten

Konfigurationsdaten, z. B. Datenbankdateiname und Pfad, können als Konstanten in Ihrer App gespeichert werden. Das Beispielprojekt enthält eine Datei "Constants.cs ", die allgemeine Konfigurationsdaten bereitstellt:

public static class Constants
{
    public const string DatabaseFilename = "TodoSQLite.db3";

    public const SQLite.SQLiteOpenFlags Flags =
        // open the database in read/write mode
        SQLite.SQLiteOpenFlags.ReadWrite |
        // create the database if it doesn't exist
        SQLite.SQLiteOpenFlags.Create |
        // enable multi-threaded database access
        SQLite.SQLiteOpenFlags.SharedCache;

    public static string DatabasePath =>
        Path.Combine(FileSystem.AppDataDirectory, DatabaseFilename);
}

In diesem Beispiel gibt die Konstantendatei Standardenumwerte SQLiteOpenFlag an, die zum Initialisieren der Datenbankverbindung verwendet werden. Die SQLiteOpenFlag Enumeration unterstützt die folgenden Werte:

  • Create: Die Verbindung erstellt die Datenbankdatei automatisch, wenn sie nicht vorhanden ist.
  • FullMutex: Die Verbindung wird im serialisierten Threadingmodus geöffnet.
  • NoMutex: Die Verbindung wird im Multithreadingmodus geöffnet.
  • PrivateCache: Die Verbindung nimmt nicht am freigegebenen Cache teil, auch wenn sie aktiviert ist.
  • ReadWrite: Die Verbindung kann Daten lesen und schreiben.
  • SharedCache: Die Verbindung nimmt an dem freigegebenen Cache teil, wenn sie aktiviert ist.
  • ProtectionComplete: Die Datei ist verschlüsselt und nicht zugänglich, während das Gerät gesperrt ist.
  • ProtectionCompleteUnlessOpen: Die Datei wird verschlüsselt, bis sie geöffnet wird, aber dann auch dann zugänglich ist, wenn der Benutzer das Gerät sperrt.
  • ProtectionCompleteUntilFirstUserAuthentication: Die Datei wird verschlüsselt, bis der Benutzer das Gerät gestartet und entsperrt hat.
  • ProtectionNone: Die Datenbankdatei ist nicht verschlüsselt.

Je nachdem, wie Die Datenbank verwendet wird, müssen Sie möglicherweise unterschiedliche Flags angeben. Weitere Informationen SQLiteOpenFlagsfinden Sie unter Öffnen einer neuen Datenbank Verbinden ion auf sqlite.org.

Erstellen einer Datenbankzugriffsklasse

Eine Datenbankwrapperklasse abstrahiert die Datenzugriffsebene von der restlichen App. Diese Klasse zentralisiert die Abfragelogik und vereinfacht die Verwaltung der Datenbankinitialisierung, wodurch es einfacher wird, Datenvorgänge zu umgestalten oder zu erweitern, wenn die App wächst. Die Beispiel-App definiert eine TodoItemDatabase Klasse für diesen Zweck.

Faule Initialisierung

Die TodoItemDatabase asynchrone lazy Initialisierung wird verwendet, um die Initialisierung der Datenbank zu verzögern, bis der erste Zugriff erfolgt, mit einer einfachen Init Methode, die von jeder Methode in der Klasse aufgerufen wird:

public class TodoItemDatabase
{
    SQLiteAsyncConnection Database;

    public TodoItemDatabase()
    {
    }

    async Task Init()
    {
        if (Database is not null)
            return;

        Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
        var result = await Database.CreateTableAsync<TodoItem>();
    }
    ...
}

Methoden für die Bearbeitung von Daten

Die TodoItemDatabase Klasse enthält Methoden für die vier Arten von Datenmanipulation: Erstellen, Lesen, Bearbeiten und Löschen. Die SQLite.NET-Bibliothek stellt eine einfache objektrelationale Zuordnung (OBJECT Relational Map, ORM) bereit, mit der Sie Objekte speichern und abrufen können, ohne SQL-Anweisungen zu schreiben.

Das folgende Beispiel zeigt die Datenmanipulationsmethoden in der Beispiel-App:

public class TodoItemDatabase
{
    ...
    public async Task<List<TodoItem>> GetItemsAsync()
    {
        await Init();
        return await Database.Table<TodoItem>().ToListAsync();
    }

    public async Task<List<TodoItem>> GetItemsNotDoneAsync()
    {
        await Init();
        return await Database.Table<TodoItem>().Where(t => t.Done).ToListAsync();

        // SQL queries are also possible
        //return await Database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
    }

    public async Task<TodoItem> GetItemAsync(int id)
    {
        await Init();
        return await Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();
    }

    public async Task<int> SaveItemAsync(TodoItem item)
    {
        await Init();
        if (item.ID != 0)
            return await Database.UpdateAsync(item);
        else
            return await Database.InsertAsync(item);
    }

    public async Task<int> DeleteItemAsync(TodoItem item)
    {
        await Init();
        return await Database.DeleteAsync(item);
    }
}

Zugreifen auf Daten

Die TodoItemDatabase Klasse kann als Singleton registriert werden, der in der gesamten App verwendet werden kann, wenn Sie Abhängigkeitseinfügungen verwenden. Sie können beispielsweise Ihre Seiten und die Datenbankzugriffsklasse als Dienste für das IServiceCollection Objekt, in MauiProgram.cs, mit den AddSingleton folgenden AddTransient Methoden registrieren:

builder.Services.AddSingleton<TodoListPage>();
builder.Services.AddTransient<TodoItemPage>();

builder.Services.AddSingleton<TodoItemDatabase>();

Diese Dienste können dann automatisch in Klassenkonstruktoren eingefügt und darauf zugegriffen werden:

TodoItemDatabase database;

public TodoItemPage(TodoItemDatabase todoItemDatabase)
{
    InitializeComponent();
    database = todoItemDatabase;
}

async void OnSaveClicked(object sender, EventArgs e)
{
    if (string.IsNullOrWhiteSpace(Item.Name))
    {
        await DisplayAlert("Name Required", "Please enter a name for the todo item.", "OK");
        return;
    }

    await database.SaveItemAsync(Item);
    await Shell.Current.GoToAsync("..");
}

Alternativ können neue Instanzen der Datenbankzugriffsklasse erstellt werden:

TodoItemDatabase database;

public TodoItemPage()
{
    InitializeComponent();
    database = new TodoItemDatabase();
}

Weitere Informationen zur Abhängigkeitsinjektion in .NET MAUI-Apps finden Sie unter Dependency Injection.

Erweiterte Konfiguration

SQLite bietet eine robuste API mit mehr Features, als in diesem Artikel und in der Beispiel-App behandelt werden. In den folgenden Abschnitten werden Features behandelt, die für skalierbarkeit wichtig sind.

Weitere Informationen finden Sie in der SQLite-Dokumentation zu sqlite.org.

Schreibschutzprotokollierung

Standardmäßig verwendet SQLite ein herkömmliches Rollbackjournal. Eine Kopie des unveränderten Datenbankinhalts wird in eine separate Rollbackdatei geschrieben, dann werden die Änderungen direkt in die Datenbankdatei geschrieben. Der COMMIT tritt auf, wenn das Rollbackjournal gelöscht wird.

Write-Ahead Logging (WAL) schreibt Zuerst Änderungen in eine separate WAL-Datei. Im WAL-Modus ist ein COMMIT ein spezieller Datensatz, der an die WAL-Datei angefügt wird, sodass mehrere Transaktionen in einer einzigen WAL-Datei auftreten können. Eine WAL-Datei wird in einem speziellen Vorgang, der als Prüfpunkt bezeichnet wird, wieder in die Datenbankdatei zusammengeführt.

WAL kann für lokale Datenbanken schneller sein, da Leser und Autoren sich nicht gegenseitig blockieren, sodass Lese- und Schreibvorgänge gleichzeitig ausgeführt werden können. Der WAL-Modus lässt jedoch keine Änderungen an der Seitengröße zu, fügt der Datenbank zusätzliche Dateizuordnungen hinzu und fügt den zusätzlichen Prüfpunktvorgang hinzu.

Um WAL in SQLite.NET zu aktivieren, rufen Sie die EnableWriteAheadLoggingAsync Methode für die SQLiteAsyncConnection Instanz auf:

await Database.EnableWriteAheadLoggingAsync();

Weitere Informationen finden Sie unter SQLite Write-Ahead Logging on sqlite.org.

Kopieren einer Datenbank

Es gibt mehrere Fälle, in denen es erforderlich sein kann, eine SQLite-Datenbank zu kopieren:

  • Eine Datenbank wurde mit Ihrer Anwendung ausgeliefert, muss jedoch auf dem mobilen Gerät in schreibbaren Speicher kopiert oder verschoben werden.
  • Sie müssen eine Sicherungskopie oder Kopie der Datenbank erstellen.
  • Sie müssen die Datenbankdatei versionieren, verschieben oder umbenennen.

Im Allgemeinen ist das Verschieben, Umbenennen oder Kopieren einer Datenbankdatei derselbe Prozess wie jeder andere Dateityp mit einigen zusätzlichen Überlegungen:

  • Alle Datenbankverbindungen sollten geschlossen werden, bevor Sie versuchen, die Datenbankdatei zu verschieben.
  • Wenn Sie die Write-Ahead-Protokollierung verwenden, erstellt SQLite eine Datei für den Freigegebenen Speicherzugriff (.shm) und eine (Write Ahead Log) (.wal)-Datei. Stellen Sie sicher, dass Sie alle Änderungen auch auf diese Dateien anwenden.