演習: SQLite を非同期で使用する

完了

アプリケーションは正しく機能しています。しかし、データベースに多くの行が含まれている場合、アプリでデータベース クエリやその他の操作が実行されている間は UI が応答しなくなることがあります。 この演習では、アプリケーションを同期型の SQLite API から非同期型に変換します。 そうすることで、データベースに対して行ったクエリの数に関係なく、アプリケーションで常に応答できるようになります。

非同期接続の作成

  1. People プロジェクト内の PersonRepository.cs ファイルを開きます。

  2. Init メソッドの定義を async に変更します。 メソッドの戻り値の型を Task に変更します。

  3. conn プロパティを SQLiteAsyncConnection に変更し、接続を初期化する Init メソッドのコードを更新します。

  4. 同期 CreateTable メソッドの呼び出しを、非同期 CreateTableAsync メソッドに置き換えます。

    完成したコードはこのようになるはずです。

    private SQLiteAsyncConnection conn;
    
    private async Task Init()
    {
        if (conn != null)
            return;
    
        conn = new SQLiteAsyncConnection(_dbPath);
    
        await conn.CreateTableAsync<Person>();
    }
    

項目をテーブルに非同期で挿入する

  1. AddNewPerson メソッドの定義を async に変更します。 メソッドの戻り値の型を Task に変更します。

  2. Initasync メソッドになったため、await キーワードを Init メソッド呼び出しに追加します。

  3. 非同期挿入操作を使用して、新しい Person を挿入するように AddNewPerson メソッドを更新します。

    コードは、次のようになります。

    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);
       }
    }
    

テーブルからすべての項目を非同期で取得する

  1. GetAllPeople メソッドの定義を変更します。 このメソッドは async にして、Task<List<Person>> オブジェクトを返す必要があります。

  2. Init メソッド呼び出しに await キーワードを追加します。

  3. 非同期呼び出しを使用して結果を返すようにメソッドを更新します。

    コードは、次のようになります。

    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>();
    }
    
  4. PersonRepository.cs ファイルを保存します。

非同期機能をテストする

  1. ソリューション エクスプローラーで [MainPage.xaml] を展開し、MainPage.xaml.cs ファイルを開きます。

  2. PersonRepository クラスの非同期メソッドを使用するように、両方のボタンクリック イベント ハンドラーを変更します。 async および await キーワードを利用します。

      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;
      }
    
  3. MainPage.xaml.cs ファイルを保存します。

  4. Windows と Android でプログラムをビルドして実行し、以前と同様に機能することを確認します。