In questa lezione verrà illustrata la procedura per creare un nuovo database memorizzandolo all’interno del dispositivo. Verranno inoltre definite alcune operazioni CRUD di base per la gestione dei contenuti del database. Per maggiore chiarezza e semplicità, l’esempio proposto non farà uso dell’approccio MVVM, che è fondamentale per una migliore organizzazione della soluzione.
Creazione del database
Creiamo all’interno del progetto Portable la cartella Data che conterrà la classe RecipesDAO
per la gestione e l’accesso al database di ricette. Si ricorda che DAO è l’acronimo di Data Access Object.
All’interno della classe definiamo due variabili private:
private SQLiteConnection database;
private static object collisionLock = new object();
dove la variabile database
memorizzerà la stringa di connessione al database, mentre collisionLock
è un oggetto che servirà a evitare i conflitti durante le operazioni CRUD mediante la definizione di appositi blocchi (lock
).
Successivamente, va definito il costruttore della classe che impiegherà al suo interno due metodi:
GetConnection
, richiamato attraverso il metodoGet
diDependecyService
;CreateTable<T>
, doveT
rappresenta un tipo generico e deve essere sostituito con la classe di interesse da usare per creare e popolare il database. Se la tabella esiste, il metodo non la sovrascriverà.
Di seguito si riporta la definizione del costruttore:
public RecipesDAO()
{
database = DependencyService.Get<IRecipesDatabaseConnection>().GetConnection();
database.CreateTable<RecipeModel>();
}
Creiamo ora una nuova istanza del database all’avvio dell’applicazione. Nella classe App
, definiamo la proprietà Database
di tipo RecipesDAO
come segue:
public static RecipesDAO Database
{
get
{
if (database == null)
{
database = new RecipesDAO();
}
return database;
}
}
In questo modo sarà possibile accedere al database in ogni pagina dell’applicazione semplicemente richiamando la proprietà Database
.
Operazioni CRUD
SQLite.NET ORM offre diversi metodi attraverso la classe SQLiteConnection
per definire le query:
Campo | Descrizione |
---|---|
Insert |
Aggiunge un nuovo oggetto al database |
Get<T> |
Data una chiave primaria, recupera il corrispettivo oggetto, se esistente |
Table<T> |
Restituisce tutti gli elementi di una tabella |
Update |
Dato un elemento già esistente che è stato modificato, il metodo aggiorna i relativi campi della tabella |
Delete |
Cancella un oggetto dal database usando la chiave primaria |
Query<T> |
Permette di scrivere una query che ritornerà un certo numero di oggetti |
La classe responsabile di fornire le operazioni CRUD è, in questo caso, la classe RecipesDAO
che farà le interrogazioni al database per inserire, cancellare o ottenere una ricetta e ottenere una lista di ricette.
Inserimento o aggiornamento di una ricetta
public int SaveRecipe(RecipeModel recipe)
{
lock (collisionLock)
{
if (recipe.Id != 0)
{
database.Update(recipe);
return recipe.Id;
}
else
{
return database.Insert(recipe);
}
}
}
Cancellazione di una ricetta dato il suo ID
public int DeleteRecipe(int id)
{
lock (collisionLock)
{
return database.Delete<RecipeModel>(id);
}
}
Recupero di una ricetta dato il suo ID
public RecipeModel GetRecipe(int id)
{
lock (collisionLock)
{
return database.Table<RecipeModel>().FirstOrDefault(x => x.Id == id);
}
}
Visualizzazione di tutte le ricette presenti nel database
public IEnumerable<RecipeModel> GetRecipes ()
{
lock (collisionLock) {
return (from i in database.Table<Recipes>() select i).ToList();
}
}
Visualizzazione e gestione dei dati
Aggiungiamo ora due nuove pagine Form Xaml Page, SQLiteDatabaseExample
e SQLiteDatabaseRecipeDetailsExample
, per la visualizzazione e la gestione dei dati forniti dal database. In particolare, in SQLiteDatabaseExample
sarà possibile visualizzare la lista di ricette disponibili e, cliccando su una di queste, si verrà rimandati alla pagina SQLiteDatabaseRecipeDetailsExample
.
Per permettere la navigazione tra queste pagine, è necessario aggiungere la pagina da visualizzare all’interno del costruttore della classe App
, definendo un nuovo oggetto NavigationPage
(codice). Inoltre, per semplificare l’interfaccia utente, inseriamo all’interno del costruttore di SQLiteDatabaseExample
il codice necessario per la definizione di una toolbar dotata di un bottone per l’aggiunta di una nuova ricetta (codice).
Sempre nel code-behind di SQLiteDatabaseExample
, aggiungiamo i seguenti due metodi:
Metodo | Descrizione |
---|---|
OnAppearing |
permetterà all’app di visualizzare tutte le ricette presenti nel database usando il metodo GetRecipes del DAO |
listItemSelected |
Metodo definito per la lista presente nel codice Xaml che invia l’utente alla pagina di gestione e dettagli della ricetta selezionata sfruttando la proprietà BindingContext della pagina di dettagli e il metodo PushAsync di Navigation |
Non resta a questo punto che definire il comportamento della pagina SQLiteDatabaseRecipeDetailsExample
in modo da permettere l’aggiunta e la gestione di nuove ricette.
Tale pagina si comporrà di una semplice form composta da tre campi (Name
, Type
, Time
) che, una volta popolati, permetteranno di salvare e cancellare la ricetta in esame attraverso gli appositi bottoni Save
e Delete
, che richiameranno i metodi proposti dal DAO. Ad esempio:
void saveClicked(object sender, EventArgs e)
{
var recipe = (RecipeModel)BindingContext;
App.Database.SaveRecipe(recipe);
this.Navigation.PopAsync();
}
Si riporta al seguente link il codice XAML della pagina, mentre il code-behind è reperibile qui.
Lanciamo l’app sui tre OS e vedremo che la schermata è vuota in quanto il database è stato appena creato e non ha alcun dato da mostrare.
Cliccando sul bottone aggiungi veniamo rimandati alla pagina di inserimento e dettagli in cui è possibile salvare/aggiornare una ricetta, cancellarla o terminare questa operazione tornando indietro.
Salvata la ricetta, l’app rimanderà l’utente alla pagina principale e permetterà a quest’ultimo di aggiungere nuove ricette o di modificare quelle esistenti semplicemente cliccando sulla ricetta e modificando dalla pagina di gestione delle ricette le informazioni di interesse.
Approfondimento
Spesso accade che l’app debba essere rilasciata sul mercato con un database opportunamente popolato. Questo argomento non è oggetto di questa guida, si rimanda pertanto il lettore alla seguente guida ufficiale di Xamarin.