Share via


Verwenden von ADO.NET mit Xamarin.iOS

Xamarin verfügt über integrierte Unterstützung für die SQLite-Datenbank, die unter iOS verfügbar ist und mithilfe der vertrauten ADO.NET-ähnlichen Syntax verfügbar ist. Wenn Sie diese APIs verwenden, müssen Sie SQL-Anweisungen schreiben, die von SQLite verarbeitet werden, z CREATE TABLE. B. , INSERT und SELECT - Anweisungen.

Assemblyverweise

Um den Zugriff auf SQLite über ADO.NET zu verwenden, müssen Sie wie hier gezeigt Verweise auf Ihr iOS-Projekt hinzufügen System.DataMono.Data.Sqlite (beispiele in Visual Studio für Mac und Visual Studio):

Klicken Sie mit der rechten Maustaste auf Verweise > bearbeiten... und klicken Sie dann, um die erforderlichen Assemblys auszuwählen.

Informationen zu Mono.Data.Sqlite

Wir verwenden die Mono.Data.Sqlite.SqliteConnection -Klasse, um eine leere Datenbankdatei zu erstellen und dann Objekte zu instanziieren SqliteCommand , die wir zum Ausführen von SQL-Anweisungen für die Datenbank verwenden können.

  1. Erstellen einer leeren Datenbank : Rufen Sie die CreateFile Methode mit einem gültigen (also schreibbaren) Dateipfad auf. Sie sollten überprüfen, ob die Datei bereits vorhanden ist, bevor Sie diese Methode aufrufen. Andernfalls wird eine neue (leere) Datenbank über der alten Datenbank erstellt, und die Daten in der alten Datei gehen verloren:

    Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath);

    Hinweis

    Die dbPath Variable sollte gemäß den weiter oben in diesem Dokument erläuterten Regeln bestimmt werden.

  2. Erstellen einer Datenbankverbindung : Nachdem die SQLite-Datenbankdatei erstellt wurde, können Sie ein Verbindungsobjekt für den Zugriff auf die Daten erstellen. Die Verbindung wird mit einer Verbindungszeichenfolge erstellt, die die Form von Data Source=file_patherhält, wie hier gezeigt:

    var connection = new SqliteConnection ("Data Source=" + dbPath);
    connection.Open();
    // do stuff
    connection.Close();
    

    Wie bereits erwähnt, sollte eine Verbindung nie über verschiedene Threads hinweg wiederverwendet werden. Erstellen Sie im Zweifelsfall die Verbindung nach Bedarf, und schließen Sie sie, wenn Sie fertig sind. Aber achten Sie darauf, dies auch häufiger als erforderlich zu tun.

  3. Erstellen und Ausführen eines Datenbankbefehls : Sobald eine Verbindung hergestellt wurde, können wir beliebige SQL-Befehle für ihn ausführen. Der folgende Code zeigt eine CREATE TABLE-Anweisung, die ausgeführt wird.

    using (var command = connection.CreateCommand ()) {
        command.CommandText = "CREATE TABLE [Items] ([_id] int, [Symbol] ntext, [Name] ntext);";
        var rowcount = command.ExecuteNonQuery ();
    }
    

Wenn Sie SQL direkt für die Datenbank ausführen, sollten Sie die normalen Vorsichtsmaßnahmen ergreifen, um keine ungültigen Anforderungen zu stellen, z. B. den Versuch, eine bereits vorhandene Tabelle zu erstellen. Behalten Sie die Struktur Ihrer Datenbank im Auge, damit Sie keine SqliteException wie "SQLite-Fehlertabelle [Items] bereits vorhanden" verursachen.

Einfacher Datenzugriff

Der DataAccess_Basic Beispielcode für dieses Dokument sieht bei der Ausführung unter iOS wie folgt aus:

Beispiel für iOS-ADO.NET

Der folgende Code veranschaulicht, wie einfache SQLite-Vorgänge ausgeführt werden, und zeigt die Ergebnisse als Text im Standard Fenster der Anwendung an.

Sie müssen die folgenden Namespaces einschließen:

using System;
using System.IO;
using Mono.Data.Sqlite;

Das folgende Codebeispiel zeigt eine gesamte Datenbankinteraktion:

  1. Erstellen der Datenbankdatei
  2. Einfügen einiger Daten
  3. Abfragen der Daten

Diese Vorgänge werden in der Regel an mehreren Stellen im gesamten Code angezeigt. Sie können beispielsweise die Datenbankdatei und -tabellen erstellen, wenn Ihre Anwendung zum ersten Mal gestartet wird, und Datenlese- und Schreibvorgänge auf einzelnen Bildschirmen in Ihrer App ausführen. Im folgenden Beispiel wurden in einer einzelnen Methode für dieses Beispiel gruppiert:

public static SqliteConnection connection;
public static string DoSomeDataAccess ()
{
    // determine the path for the database file
    string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal),
        "adodemo.db3");

    bool exists = File.Exists (dbPath);

    if (!exists) {
        Console.WriteLine("Creating database");
        // Need to create the database before seeding it with some data
        Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath);
        connection = new SqliteConnection ("Data Source=" + dbPath);

        var commands = new[] {
            "CREATE TABLE [Items] (_id ntext, Symbol ntext);",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'AAPL')",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('2', 'GOOG')",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('3', 'MSFT')"
        };
        // Open the database connection and create table with data
        connection.Open ();
        foreach (var command in commands) {
            using (var c = connection.CreateCommand ()) {
                c.CommandText = command;
                var rowcount = c.ExecuteNonQuery ();
                Console.WriteLine("\tExecuted " + command);
            }
        }
    } else {
        Console.WriteLine("Database already exists");
        // Open connection to existing database file
        connection = new SqliteConnection ("Data Source=" + dbPath);
        connection.Open ();
    }

    // query the database to prove data was inserted!
    using (var contents = connection.CreateCommand ()) {
        contents.CommandText = "SELECT [_id], [Symbol] from [Items]";
        var r = contents.ExecuteReader ();
        Console.WriteLine("Reading data");
        while (r.Read ())
            Console.WriteLine("\tKey={0}; Value={1}",
                              r ["_id"].ToString (),
                              r ["Symbol"].ToString ());
    }
    connection.Close ();
}

Komplexere Abfragen

Da SQLite die Ausführung beliebiger SQL-Befehle für die Daten zulässt, können Sie beliebige CREATE-, INSERT-, UPDATE-, DELETE- oder SELECT-Anweisungen ausführen. Informationen zu den SQL-Befehlen, die von SQLite unterstützt werden, finden Sie auf der Sqlite-Website. Die SQL-Anweisungen werden mit einer von drei Methoden für ein SqliteCommand-Objekt ausgeführt:

  • ExecuteNonQuery : Wird in der Regel für die Tabellenerstellung oder das Einfügen von Daten verwendet. Der Rückgabewert für einige Vorgänge ist die Anzahl der betroffenen Zeilen, andernfalls -1.
  • ExecuteReader : Wird verwendet, wenn eine Auflistung von Zeilen als SqlDataReader zurückgegeben werden soll.
  • ExecuteScalar : Ruft einen einzelnen Wert (z. B. ein Aggregat) ab.

EXECUTENONQUERY

INSERT-, UPDATE- und DELETE-Anweisungen geben die Anzahl der betroffenen Zeilen zurück. Alle anderen SQL-Anweisungen geben -1 zurück.

using (var c = connection.CreateCommand ()) {
    c.CommandText = "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'APPL')";
    var rowcount = c.ExecuteNonQuery (); // rowcount will be 1
}

EXECUTEREADER

Die folgende Methode zeigt eine WHERE-Klausel in der SELECT-Anweisung. Da der Code eine vollständige SQL-Anweisung gestaltet, muss er darauf achten, reservierte Zeichen wie das Anführungszeichen (') um Zeichenfolgen zu escapen.

public static string MoreComplexQuery ()
{
    var output = "";
    output += "\nComplex query example: ";
    string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal), "ormdemo.db3");

    connection = new SqliteConnection ("Data Source=" + dbPath);
    connection.Open ();
    using (var contents = connection.CreateCommand ()) {
        contents.CommandText = "SELECT * FROM [Items] WHERE Symbol = 'MSFT'";
        var r = contents.ExecuteReader ();
        output += "\nReading data";
        while (r.Read ())
            output += String.Format ("\n\tKey={0}; Value={1}",
                    r ["_id"].ToString (),
                    r ["Symbol"].ToString ());
    }
    connection.Close ();

    return output;
}

Die ExecuteReader-Methode gibt ein SqliteDataReader-Objekt zurück. Neben der im Beispiel gezeigten Read-Methode sind weitere nützliche Eigenschaften enthalten:

  • Betroffene Zeilen : Anzahl der zeilen, die von der Abfrage betroffen sind.
  • HasRows : Gibt an, ob Zeilen zurückgegeben wurden.

EXECUTESCALAR

Verwenden Sie dies für SELECT-Anweisungen, die einen einzelnen Wert (z. B. ein Aggregat) zurückgeben.

using (var contents = connection.CreateCommand ()) {
    contents.CommandText = "SELECT COUNT(*) FROM [Items] WHERE Symbol <> 'MSFT'";
    var i = contents.ExecuteScalar ();
}

Der ExecuteScalar Rückgabetyp der Methode lautet object – Sie sollten das Ergebnis abhängig von der Datenbankabfrage umwandeln. Das Ergebnis kann eine ganze Zahl aus einer COUNT-Abfrage oder eine Zeichenfolge aus einer einzelnen SPALTE SELECT-Abfrage sein. Beachten Sie, dass sich dies von anderen Execute-Methoden unterscheidet, die ein Leserobjekt oder eine Anzahl der betroffenen Zeilen zurückgeben.

Microsoft.Data.Sqlite

Es gibt eine andere Bibliothek Microsoft.Data.Sqlite, die über NuGet installiert werden kann, die funktionell gleichwertig Mono.Data.Sqlite ist und dieselben Arten von Abfragen zulässt.

Es gibt einen Vergleich zwischen den beiden Bibliotheken und einigen Xamarin-spezifischen Details. Am wichtigsten für Xamarin.iOS-Apps müssen Sie einen Initialisierungsaufruf einschließen:

// required for Xamarin.iOS
SQLitePCL.Batteries_V2.Init();