Exercise: Use SQLite asynchronously
The application works well, but if the database contains many rows, the UI can become unresponsive while the app performs database queries and other operations. In this exercise, you convert the application from the synchronous SQLite API to the asynchronous version. This way, your application is always responsive no matter how many queries you make to your database.
Create an Async connection
Open the PersonRepository.cs file in the People project.
Modify the
Init
method's definition to beasync
. Change the return type of the method toTask
.Change the
conn
property to aSQLiteAsyncConnection
and update the code in theInit
method that initializes the connection.Replace the call to the synchronous
CreateTable
method with the asynchronousCreateTableAsync
method.The completed code should look like this:
private SQLiteAsyncConnection conn; private async Task Init() { if (conn != null) return; conn = new SQLiteAsyncConnection(_dbPath); await conn.CreateTableAsync<Person>(); }
Insert an item into a table asynchronously
Modify the definition of the
AddNewPerson
method to beasync
. Change the return type of the method toTask
.Add the
await
keyword to theInit
method call becauseInit
is now anasync
method.Update the
AddNewPerson
method to insert a newPerson
by using an asynchronous insert operation.The code should look like this:
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); } }
Get all items from a table asynchronously
Modify the
GetAllPeople
method definition. This method should beasync
and return aTask<List<Person>>
object.Add the
await
keyword to theInit
method call.Update the method to return the results by using an asynchronous call.
The code should look like this:
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>(); }
Save the PersonRepository.cs file.
Test the asynchronous functionality
Expand MainPage.xaml in the Solution Explorer and open the MainPage.xaml.cs file.
Modify both of the button-click event handlers so that they use the asynchronous methods from the
PersonRepository
class. Make use of theasync
andawait
keywords: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; }
Save the MainPage.xaml.cs file.
Build and run the program on Windows and Android, verifying that it still functions as before.