Condividi tramite


Uso di ADO.NET con Xamarin.iOS

Xamarin include il supporto predefinito per il database SQLite disponibile in iOS, esposto con ADO familiare. Sintassi simile a NET. L'uso di queste API richiede di scrivere istruzioni SQL elaborate da SQLite, ad esempio CREATE TABLEistruzioni e INSERTSELECT .

Riferimenti dell'assembly

Per usare l'accesso a SQLite tramite ADO.NET è necessario aggiungere System.Data e Mono.Data.Sqlite riferimenti al progetto iOS, come illustrato di seguito (per esempi in Visual Studio per Mac e Visual Studio):

Fare clic con il pulsante destro del mouse su Riferimenti > modifica riferimenti, quindi scegliere per selezionare gli assembly necessari.

Informazioni su Mono.Data.Sqlite

Verrà usata la Mono.Data.Sqlite.SqliteConnection classe per creare un file di database vuoto e quindi per creare un'istanza di SqliteCommand oggetti che è possibile usare per eseguire istruzioni SQL sul database.

  1. Creazione di un database vuoto: chiamare il CreateFile metodo con un percorso di file valido (ad esempio scrivibile). È necessario verificare se il file esiste già prima di chiamare questo metodo. In caso contrario, verrà creato un nuovo database (vuoto) nella parte superiore di quella precedente e i dati nel file precedente andranno persi:

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

    Nota

    La dbPath variabile deve essere determinata in base alle regole descritte in precedenza in questo documento.

  2. Creazione di un Connessione database: dopo aver creato il file di database SQLite, è possibile creare un oggetto connessione per accedere ai dati. La connessione viene costruita con un stringa di connessione che assume la forma di Data Source=file_path, come illustrato di seguito:

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

    Come accennato in precedenza, una connessione non deve mai essere riutilizzata tra thread diversi. In caso di dubbio, creare la connessione come richiesto e chiuderla al termine; ma essere consapevoli di fare questo più spesso di quanto richiesto troppo.

  3. Creazione ed esecuzione di un comando di database: dopo aver creato una connessione, è possibile eseguire comandi SQL arbitrari. Il codice seguente mostra un'istruzione CREATE TABLE in esecuzione.

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

Quando si esegue SQL direttamente sul database, è consigliabile adottare le normali precauzioni per non effettuare richieste non valide, ad esempio il tentativo di creare una tabella già esistente. Tenere traccia della struttura del database in modo che non si causi un'eccezione SqliteException, ad esempio "Tabella errori SQLite [Items] già esistente".

Accesso ai dati di base

Il codice di esempio DataAccess_Basic per questo documento è simile al seguente durante l'esecuzione in iOS:

iOS ADO.NET sample

Il codice seguente illustra come eseguire semplici operazioni SQLite e mostra i risultati come testo nella finestra principale dell'applicazione.

È necessario includere questi spazi dei nomi:

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

L'esempio di codice seguente illustra un'intera interazione del database:

  1. Creazione del file di database
  2. Inserimento di alcuni dati
  3. Eseguire query sui dati

Queste operazioni vengono in genere visualizzate in più posizioni nel codice, ad esempio è possibile creare il file di database e le tabelle all'avvio dell'applicazione ed eseguire operazioni di lettura e scrittura dei dati in singole schermate dell'app. Nell'esempio seguente sono stati raggruppati in un singolo metodo per questo esempio:

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

Query più complesse

Poiché SQLite consente l'esecuzione di comandi SQL arbitrari sui dati, è possibile eseguire qualsiasi istruzione CREATE, IN edizione Standard RT, UPDATE, DELETE o edizione Standard LECT desiderata. Per informazioni sui comandi SQL supportati da SQLite, vedere il sito Web Sqlite. Le istruzioni SQL vengono eseguite usando uno dei tre metodi in un oggetto SqliteCommand:

  • ExecuteNonQuery : in genere usato per la creazione o l'inserimento di dati della tabella. Il valore restituito per alcune operazioni è il numero di righe interessate, altrimenti è -1.
  • ExecuteReader : usato quando una raccolta di righe deve essere restituita come SqlDataReader .
  • ExecuteScalar : recupera un singolo valore, ad esempio un'aggregazione.

EXECUTENONQUERY

Le istruzioni IN edizione Standard RT, UPDATE e DELETE restituiranno il numero di righe interessate. Tutte le altre istruzioni SQL restituiranno -1.

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

EXECUTEREADER

Il metodo seguente illustra una clausola WHERE nell'istruzione edizione Standard LECT. Poiché il codice sta creando un'istruzione SQL completa, è necessario eseguire l'escape di caratteri riservati, ad esempio la citazione (') intorno alle stringhe.

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

Il metodo ExecuteReader restituisce un oggetto SqliteDataReader. Oltre al metodo Read illustrato nell'esempio, altre proprietà utili includono:

  • RowsAffected : conteggio delle righe interessate dalla query.
  • HasRows : indica se sono state restituite righe.

EXECUTESCALAR

Usare questa opzione per le istruzioni edizione Standard LECT che restituiscono un singolo valore, ad esempio un'aggregazione.

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

Il ExecuteScalar tipo restituito del metodo è object : è necessario eseguire il cast del risultato a seconda della query del database. Il risultato può essere un numero intero da una query COUNT o una stringa da una singola colonna edizione Standard QUERYLECT. Si noti che questo comportamento è diverso da altri metodi Execute che restituiscono un oggetto lettore o un conteggio del numero di righe interessate.

Microsoft.Data.Sqlite

È disponibile un'altra libreria Microsoft.Data.Sqlite, che può essere installata da NuGet, che è funzionalmente equivalente a Mono.Data.Sqlite e consente gli stessi tipi di query.

Esiste un confronto tra le due librerie e alcuni dettagli specifici di Xamarin. Più importante per le app Xamarin.iOS, è necessario includere una chiamata di inizializzazione:

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