Esercizio - Usare SQLite in modo asincrono
L'applicazione funziona bene, ma se il database contiene molte righe l'interfaccia utente può smettere di rispondere mentre l'app esegue query e altre operazioni sul database. In questo esercizio l'applicazione viene convertita dall'API SQLite sincrona alla versione asincrona. In questo modo, l'applicazione rimane sempre reattiva, indipendentemente dal numero di query eseguite nel database.
Creare una connessione asincrona
Aprire il file PersonRepository.cs nel progetto People.
Modificare la definizione del metodo
Init
in modo che siaasync
. Cambiare il tipo restituito del metodo inTask
.Modificare la proprietà
conn
in unSQLiteAsyncConnection
e aggiornare il codice nel metodoInit
che inizializza la connessione.Sostituire la chiamata al metodo sincrono
CreateTable
con il metodo asincronoCreateTableAsync
.Il codice completato avrà l'aspetto seguente:
private SQLiteAsyncConnection conn; private async Task Init() { if (conn != null) return; conn = new SQLiteAsyncConnection(_dbPath); await conn.CreateTableAsync<Person>(); }
Inserire un elemento in una tabella in modo asincrono
Modificare la definizione del metodo
AddNewPerson
in modo che siaasync
. Cambiare il tipo restituito del metodo inTask
.Aggiungere la parola chiave
await
alla chiamata al metodoInit
perchéInit
è ora un metodoasync
.Aggiornare il metodo
AddNewPerson
per inserire una nuovaPerson
usando un'operazione di inserimento asincrona.Il codice dovrebbe essere simile al seguente:
using System.Threading.Tasks; ... public async Task AddNewPerson(string name) { int result = 0; try { // Call Init() await Init(); // basic validation to ensure a name was entered if (string.IsNullOrEmpty(name)) throw new Exception("Valid name required"); result = await conn.InsertAsync(new Person { Name = name }); StatusMessage = string.Format("{0} record(s) added [Name: {1})", result, name); } catch (Exception ex) { StatusMessage = string.Format("Failed to add {0}. Error: {1}", name, ex.Message); } }
Ottenere tutti gli elementi da una tabella in modo asincrono
Modificare la definizione del metodo
GetAllPeople
. Questo metodo deve essereasync
e restituire un oggettoTask<List<Person>>
.Aggiungere la parola chiave
await
alla chiamata al metodoInit
.Aggiornare il metodo in modo che restituisca i risultati usando una chiamata asincrona.
Il codice dovrebbe essere simile al seguente:
public async Task<List<Person>> GetAllPeople() { try { await Init(); return await conn.Table<Person>().ToListAsync(); } catch (Exception ex) { StatusMessage = string.Format("Failed to retrieve data. {0}", ex.Message); } return new List<Person>(); }
Salvare il file PersonRepository.cs.
Testare la funzionalità asincrona
Espandere MainPage.xaml in Esplora soluzioni e aprire il file MainPage.xaml.cs.
Modificare entrambi i gestori eventi button-click in modo che usino i metodi asincroni della classe
PersonRepository
. Usare le parole chiaveasync
eawait
:public async void OnNewButtonClicked(object sender, EventArgs args) { statusMessage.Text = ""; await App.PersonRepo.AddNewPerson(newPerson.Text); statusMessage.Text = App.PersonRepo.StatusMessage; } public async void OnGetButtonClicked(object sender, EventArgs args) { statusMessage.Text = ""; List<Person> people = await App.PersonRepo.GetAllPeople(); peopleList.ItemsSource = people; }
Salvare il file MainPage.xaml.cs.
Compilare ed eseguire il programma in Windows e Android verificando che funzioni ancora come prima.