Freigeben über


Verwenden von SQLite.NET mit Android

Die SQLite.NET Bibliothek, die Xamarin empfiehlt, ist ein sehr einfaches ORM, mit dem Sie Objekte einfach in der lokalen SQLite-Datenbank auf einem Android-Gerät speichern und abrufen können. ORM steht für Object Relational Mapping – eine API, mit der Sie "Objekte" aus einer Datenbank speichern und abrufen können, ohne SQL-Anweisungen zu schreiben.

Um die SQLite.NET-Bibliothek in eine Xamarin-App einzuschließen, fügen Sie ihrem Projekt das folgende NuGet-Paket hinzu:

SQLite.NET NuGet-Paket

Es gibt eine Reihe verschiedener SQLite-Pakete – wählen Sie unbedingt das richtige Paket aus (es ist möglicherweise nicht das oberste Ergebnis in der Suche).

Wichtig

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

Nachdem Sie die SQLite.NET Bibliothek verfügbar haben, führen Sie die folgenden drei Schritte aus, um sie für den Zugriff auf eine Datenbank zu verwenden:

  1. Fügen Sie eine using-Anweisung hinzu: Fügen Sie die folgende Anweisung zu den C#-Dateien hinzu, in denen der Datenzugriff erforderlich ist:

    using SQLite;
    
  2. Erstellen Sie eine leere Datenbank – Ein Datenbankverweis kann durch Übergeben des Dateipfads an den SQLiteConnection-Klassenkonstruktor erstellt werden. Sie müssen nicht überprüfen, ob die Datei bereits vorhanden ist – sie wird bei Bedarf automatisch erstellt, andernfalls wird die vorhandene Datenbankdatei geöffnet. Die dbPath Variable sollte gemäß den weiter oben in diesem Dokument erläuterten Regeln bestimmt werden:

    var db = new SQLiteConnection (dbPath);
    
  3. Speichern von Daten – Nachdem Sie ein SQLiteConnection-Objekt erstellt haben, werden Datenbankbefehle ausgeführt, indem sie ihre Methoden aufrufen, z. B. CreateTable und Insert wie folgt:

    db.CreateTable<Stock> ();
    db.Insert (newStock); // after creating the newStock object
    
  4. Abrufen von Daten – Verwenden Sie die folgende Syntax, um ein Objekt (oder eine Liste von Objekten) abzurufen:

    var stock = db.Get<Stock>(5); // primary key id of 5
    var stockList = db.Table<Stock>();
    

Beispiel für den Einfachen Datenzugriff

Der DataAccess_Basic Beispielcode für dieses Dokument sieht so aus, wenn es unter Android ausgeführt wird. Der Code veranschaulicht, wie sie einfache SQLite.NET Vorgänge ausführen und die Ergebnisse als Text im Hauptfenster der Anwendung anzeigen.

Android

Beispiel für Android-SQLite.NET

Das folgende Codebeispiel zeigt eine gesamte Datenbankinteraktion mithilfe der SQLite.NET-Bibliothek, um den zugrunde liegenden Datenbankzugriff zu kapseln. Es zeigt:

  1. Erstellen der Datenbankdatei

  2. Einfügen einiger Daten durch Erstellen von Objekten und anschließendes Speichern

  3. Abfragen der Daten

Sie müssen die folgenden Namespaces einschließen:

using SQLite; // from the github SQLite.cs class

Die letzte erfordert, dass Sie SQLite zu Ihrem Projekt hinzugefügt haben. Beachten Sie, dass die SQLite-Datenbanktabelle durch Hinzufügen von Attributen zu einer Klasse (der Stock Klasse) und nicht durch einen CREATE TABLE-Befehl definiert wird.

[Table("Items")]
public class Stock {
    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }
    [MaxLength(8)]
    public string Symbol { get; set; }
}
public static void DoSomeDataAccess () {
       Console.WriteLine ("Creating database, if it doesn't already exist");
   string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal),
        "ormdemo.db3");
   var db = new SQLiteConnection (dbPath);
   db.CreateTable<Stock> ();
   if (db.Table<Stock> ().Count() == 0) {
        // only insert the data if it doesn't already exist
        var newStock = new Stock ();
        newStock.Symbol = "AAPL";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "GOOG";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "MSFT";
        db.Insert (newStock);
    }
    Console.WriteLine("Reading data");
    var table = db.Table<Stock> ();
    foreach (var s in table) {
        Console.WriteLine (s.Id + " " + s.Symbol);
    }
}

Wenn Sie das [Table] Attribut ohne Angabe eines Tabellennamenparameters verwenden, hat die zugrunde liegende Datenbanktabelle denselben Namen wie die Klasse (in diesem Fall "Stock"). Der tatsächliche Tabellenname ist wichtig, wenn Sie SQL-Abfragen direkt für die Datenbank schreiben, anstatt die ORM-Datenzugriffsmethoden zu verwenden. Ebenso ist das [Column("_id")] Attribut optional, und wenn keine Spalte vorhanden ist, wird der Tabelle mit demselben Namen wie die Eigenschaft in der Klasse hinzugefügt.

SQLite-Attribute

Allgemeine Attribute, die Sie auf Ihre Klassen anwenden können, um zu steuern, wie sie in der zugrunde liegenden Datenbank gespeichert werden:

  • [PrimaryKey] – Dieses Attribut kann auf eine ganzzahlige Eigenschaft angewendet werden, um zu erzwingen, dass es der Primärschlüssel der zugrunde liegenden Tabelle ist. Zusammengesetzte Primärschlüssel werden nicht unterstützt.

  • [AutoIncrement] – Dieses Attribut bewirkt, dass der Wert einer ganzzahligen Eigenschaft für jedes neue Objekt, das in die Datenbank eingefügt wird, automatisch erhöht wird.

  • [Spalte(Name)] – Der name Parameter legt den Namen der zugrunde liegenden Datenbankspalte fest.

  • [Tabelle(Name)] – Kennzeichnet die Klasse so, dass sie in einer zugrunde liegenden SQLite-Tabelle mit dem angegebenen Namen gespeichert werden kann.

  • [MaxLength(value)] – Schränken Sie die Länge einer Texteigenschaft ein, wenn versucht wird, eine Datenbank einzufügen. Der Verbrauch von Code sollte dies überprüfen, bevor das Objekt eingefügt wird, da dieses Attribut nur "aktiviert" ist, wenn ein Datenbankeinfüge- oder Aktualisierungsvorgang versucht wird.

  • [Ignorieren] – Bewirkt, dass SQLite.NET diese Eigenschaft ignorieren. Dies ist besonders nützlich für Eigenschaften, die über einen Typ verfügen, der nicht in der Datenbank gespeichert werden kann, oder Eigenschaften, die Modellauflistungen modelliert werden können, die nicht automatisch von SQLite aufgelöst werden können.

  • [Eindeutig] – Stellt sicher, dass die Werte in der zugrunde liegenden Datenbankspalte eindeutig sind.

Die meisten dieser Attribute sind optional. Sie sollten immer einen ganzzahligen Primärschlüssel angeben, damit Auswahl- und Löschabfragen effizient für Ihre Daten ausgeführt werden können.

Komplexere Abfragen

Die folgenden Methoden SQLiteConnection können verwendet werden, um andere Datenvorgänge auszuführen:

  • Einfügen – Fügt der Datenbank ein neues Objekt hinzu.

  • Abrufen von<T> – Versucht, ein Objekt mithilfe des Primärschlüssels abzurufen.

  • Tabelle<T> – Gibt alle Objekte in der Tabelle zurück.

  • Delete – Löscht ein Objekt mithilfe seines Primärschlüssels.

  • Abfrage<T> – Ausführen einer SQL-Abfrage, die eine Anzahl von Zeilen (als Objekte) zurückgibt.

  • Execute – Verwenden Sie diese Methode (und nicht Query), wenn Sie nicht erwarten, dass Zeilen aus dem SQL -Objekt (z. B. INSERT-, UPDATE- und DELETE-Anweisungen) zurückgesendet werden.

Abrufen eines Objekts durch den Primärschlüssel

SQLite.Net stellt die Get-Methode zum Abrufen eines einzelnen Objekts basierend auf dem Primärschlüssel bereit.

var existingItem = db.Get<Stock>(3);

Auswählen eines Objekts mit Linq

Methoden, die Auflistungen zurückgeben, IEnumerable<T> damit Sie linq verwenden können, um den Inhalt einer Tabelle abzufragen oder zu sortieren. Der folgende Code zeigt ein Beispiel, in dem Linq verwendet wird, um alle Einträge herauszufiltern, die mit dem Buchstaben "A" beginnen:

var apple = from s in db.Table<Stock>()
    where s.Symbol.StartsWith ("A")
    select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);

Auswählen eines Objekts mit SQL

Obwohl SQLite.Net objektbasierten Zugriff auf Ihre Daten bereitstellen können, müssen Sie manchmal eine komplexere Abfrage ausführen, als Linq zulässt (oder Sie benötigen möglicherweise eine schnellere Leistung). Sie können SQL-Befehle mit der Query-Methode verwenden, wie hier gezeigt:

var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");
foreach (var s in stocksStartingWithA) {
    Console.WriteLine ("a " + s.Symbol);
}

Hinweis

Beim direkten Schreiben von SQL-Anweisungen erstellen Sie eine Abhängigkeit von den Namen von Tabellen und Spalten in Ihrer Datenbank, die aus Ihren Klassen und ihren Attributen generiert wurden. Wenn Sie diese Namen in Ihrem Code ändern, müssen Sie alle manuell geschriebenen SQL-Anweisungen aktualisieren.

Löschen eines Objekts

Der Primärschlüssel wird verwendet, um die Zeile zu löschen, wie hier gezeigt:

var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key

Sie können überprüfen, rowcount wie viele Zeilen betroffen waren (in diesem Fall gelöscht).

Verwenden von SQLite.NET mit mehreren Threads

SQLite unterstützt drei verschiedene Threadingmodi: Single-Thread, Multithread und Serialisiert. Wenn Sie ohne Einschränkungen auf die Datenbank aus mehreren Threads zugreifen möchten, können Sie SQLite so konfigurieren, dass der serialisierte Threadingmodus verwendet wird. Es ist wichtig, diesen Modus frühzeitig in Ihrer Anwendung festzulegen (z. B. am Anfang der OnCreate Methode).

Rufen Sie auf, um SqliteConnection.SetConfigden Threadingmodus zu ändern. Diese Codezeile konfiguriert z. B. SQLite für den serialisierten Modus:

using using Mono.Data.Sqlite;
...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);

Die Android-Version von SQLite hat eine Einschränkung, die einige weitere Schritte erfordert. Wenn der Aufruf eine SqliteConnection.SetConfig SQLite-Ausnahme erzeugt, z library used incorrectly. B. , müssen Sie die folgende Problemumgehung verwenden:

  1. Link zur systemeigenen libsqlite.so-Bibliothek , sodass die sqlite3_shutdown apIs für sqlite3_initialize die App verfügbar gemacht werden:

    [DllImport("libsqlite.so")]
    internal static extern int sqlite3_shutdown();
    
    [DllImport("libsqlite.so")]
    internal static extern int sqlite3_initialize();
    
  2. Fügen Sie am Anfang der OnCreate Methode diesen Code zum Herunterfahren von SQLite hinzu, konfigurieren Sie ihn für den serialisierten Modus, und initialisieren Sie SQLite erneut:

    using using Mono.Data.Sqlite;
    ...
    sqlite3_shutdown();
    SqliteConnection.SetConfig(SQLiteConfig.Serialized);
    sqlite3_initialize();
    

Diese Problemumgehung funktioniert auch für die Mono.Data.Sqlite Bibliothek. Weitere Informationen zu SQLite und Multithreading finden Sie unter SQLite und Multiple Threads.