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 TABLE
istruzioni e INSERT
SELECT
.
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.
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.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.
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:
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:
- Creazione del file di database
- Inserimento di alcuni dati
- 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();