Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Gestione di un database SQLite

Come utilizzare le funzionalità messe a disposizione da Xamarin.Forms per gestire i dati di un database SQLite connesso ad un'app mobile.
Come utilizzare le funzionalità messe a disposizione da Xamarin.Forms per gestire i dati di un database SQLite connesso ad un'app mobile.
Link copiato negli appunti

La quasi totalità delle app è direttamente connessa a servizi web che offrono informazioni di diversa natura da mostrare all’utente. Ciononostante, è spesso necessario salvare diverse informazioni all’interno del dispositivo stesso per rendere l’applicazione più reattiva e ovviare all’assenza della rete dati. In particolare, in presenza di una grande mole di dati da memorizzare è spesso utile per lo sviluppatore definire uno strato di accesso ai dati (Data layer) e un database.

Xamarin offre la possibilità di definire e utilizzare database SQLite sia tramite l’utilizzo del framework ADO.NET, sia tramite SQLite.NET Object Relational Mapping (ORM). Entrambe le solzuioni permettono di accedere ad un database e di gestire le informazioni in esso contenute tramite le classiche operazioni CRUD (Create, Read, Update, Delete).

SQLite si è affermato negli anni come DBMS relazione open-source ed è stato adottato fin da subito da Apple e Google per i propri sistemi. Solo in tempi recenti, Microsoft ha offerto con Windows Phone 8 la possibilità di sfruttare un database SQLite.

In questa lezion e nella successiva, ci si concentrerà sull’utilizzo di SQLite.NET ORM e sulla gestione di un database.

Configurazione dell’ambiente

Per utilizzare SQLite è necessario aggiungere al progetto Portable la libreria di supporto SQLite-net PCL attraverso NuGet (tasto destro su Referenze -> Gestisci pacchetti NuGet), installando il pacchetto avente come id sqlite-net-pcl.

Figura 75. (click per ingrandire)


Analogamente, vanno configurati anche i progetti per Android, iOS e Windows Phone installando la medesima libreria. Inoltre, Windows Phone 8.1 richiede di aggiungere la referenza a Microsoft Visual C++ 2013 Runtime Package poiché ha una dipendenza dal package SQLitePCL.raw_basic, che sarà automaticamente referenziato da NuGet.

Figura 76. (click per ingrandire)


Ora che l’ambiente è correttamente configurato è possibile procedere con la creazione di una schermata per la gestione delle ricette mediante un database SQLite.

Creazione della connessione al database

Nel progetto Portable aggiungiamo una nuova interfaccia, nominata IRecipesDatabaseConnection, che definirà il metodo per la connessione al database da implementare in ogni progetto attraverso il DependencyService. L’interfaccia definisce il metodo GetConnection() che restituisce una connessione al database di interesse.

public interface IRecipesDatabaseConnection
{
	SQLiteConnection GetConnection();
}

Aggiungiamo adesso ad ogni progetto l’implementazione dell’interfaccia.

Nel progetto Android, creiamo una nuova classe, RecipesDatabaseConnection_Android, e riportiamo il seguente codice:

[assembly: Dependency(typeof(RecipesDatabaseConnection_Android))]
			namespace HelloXamarin.Droid
			{
				public class RecipesDatabaseConnection_Android : IRecipesDatabaseConnection
				{
					public RecipesDatabaseConnection_Android() { }
					public SQLite.SQLiteConnection GetConnection()
					{
						var sqliteFilename = "RecipesDB.db3";
						string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
						var path = Path.Combine(documentsPath, sqliteFilename);
						var conn = new SQLite.SQLiteConnection(path);
						return conn;
					}
				}
			}

Quanto scritto permette di: aggiungere la dipendenza attraverso la classe Dependency; creare un costruttore vuoto della classe; implementare il metodo GetConnection dell’interfaccia. Questo metodo definisce al suo interno:

  • il nome del database a cui accederà l’applicazione;
  • il percorso in cui è reperibile il database;
  • la connessione al database che avviene attraverso la creazione di un nuovo oggetto SQLiteConnection che prende il percorso come input.

Analogamente, effettuiamo la medesima operazione per iOS (codice) e Windows Phone (codice).

Abbiamo definito la stringa di connessione al database, ma non è ancora stata definita alcuna classe che rappresenti il modello di dominio, ossia una ricetta, da mappare con una tabella nel database. Aggiungiamo al progetto Portable una nuova cartella Model che conterrà la classe RecipeModel, costituita da quattro proprietà: un ID autoincrementante, un nome, il tipo di piatto e il tempo di preparazione. Questa classe, inoltre, dovrà implementare l’interfaccia INotifyPropertyChanged per notificare le modifiche apportate ai dati da archiviare.

A titolo d’esempio si riporta una definizione parziale della classe RecipeModel al fine di introdurre la mappatura con la rispettiva tabella del database.

[Table("Recipes")]
			public class RecipeModel : INotifyPropertyChanged
				{
					private int _id;
					[PrimaryKey, AutoIncrement]
					public int Id
					{
						get
						{
							return _id;
						}
						set
						{
							this._id = value;
							OnPropertyChanged(nameof(Id));
						}
					}
					private string _name;
					[NotNull]
					public string Name
					{
						get
						{
							return _name;
						}
						set
						{
							this._name = value;
							OnPropertyChanged(nameof(Name));
						}
					}
					....
					public event PropertyChangedEventHandler PropertyChanged;
					private void OnPropertyChanged(string propertyName)
					{
						this.PropertyChanged?.Invoke(this,
							new PropertyChangedEventArgs(propertyName));
					}
				}

Come si può notare, oltre all’implementazione già vista dell’interfaccia INotifyPropertyChanged, sono state inserite delle annotazioni tra parentesi quadre. Queste annotazioni sono fondamentali per indicare il nome della tabella e le proprietà dei suoi campi, come ad esempio la chiave primaria. Di seguito è riportata una spiegazione delle annotazioni disponibili:

Annotazione Può essere applicato ad un variabile di tipo intero forzandola ad essere la chiave primaria della tabella. Non è possibile al momento avere chiavi primarie composte
[PrimaryKey] Descrizione1
[AutoIncrement] Permette al sistema di autoincrementare il valore della proprietà di tipo intero per ogni nuovo oggetto inserito nella tabella
[Column(name)] Permette di impostare il nome della colonna della tabella sostituendo quello di default, ossia il nome della proprietà
[Table(name)] Imposta la classe come tabella del database SQLite e permette di impostarne il nome sostituendo quello di default, ossia il nome della classe
[MaxLength(value)] Imposta una restrizione sulla lunghezza massima delle proprietà di tipo testuale
[Ignore] SQLite.NET ignorerà la proprietà marcata con questa annotazione. Questa annotazione è fondamentale quando la proprietà in questione non può essere salvata nel database a causa del tipo di dato
[Unique] Assicura che il valore riportato in quella tabella sia unico.

Non resta a questo punto che creare la tabella e le relative operazioni CRUD, che vedremo nella prossima lezione.

Ti consigliamo anche