2016-04-05 21 views
0

私はMVVM Light WPFアプリケーションをビルドするためにVisual Studio 2015とEntity Framework 6を​​使用しています。ユーザーが検索ボタンをクリックすると、それはビューモデルのコンストラクタで、次のように定義されているRelayCommandを呼び出します。ObservableCollectionを返す非同期検索を実行する

SearchEmployeesRelayCommand = new RelayCommand(SearchEmployees); 

ビューモデルでSearchEmployees方法は、次のようになります。

private BackgroundWorker _worker; 

public void SearchEmployees() 
{ 
    _worker = new BackgroundWorker(); // use this to show busy indicator 

    var dataService = new EmployeeDataService(); 
    _worker.DoWork += (o, ea) => 
    { 
     SearchResults = dataService.SearchEmployees(SelectedColumn, SearchValue); 
    }; 
    _worker.RunWorkerCompleted += (o, ea) => 
    { 
     IsSearching = false; 
    }; 

    IsSearching = true; 
    _worker.RunWorkerAsync(); 
} 

データサービスの検索方法は、次のようになります。

public ObservableCollection<EmployeeViewModel> 
    SearchEmployees(string selectedColumn, string searchValue) 
{ 
    var paramEmployee = Expression.Parameter(typeof(Employee), "e"); 

    var comparison = Expression.Lambda<Func<Employee, bool>>(
     Expression.Equal(
      Expression.Property(paramEmployee, selectedColumn), 
      Expression.Constant(searchValue)), 
      paramEmployee).Compile(); 

    using (var context = new MyEntities()) 
    { 
     var query = (from e in context.Employees 
        .Where(comparison) 
        select new EmployeeViewModel 
        { 
         // Various EF model properties... 
        }); 
     return new ObservableCollection<EmployeeViewModel>(query); 
    } 
} 

私は上記の方法を作るしようとした場合asyncawaitable、このようなもので:

return await new ObservableCollection<EmployeeViewModel>(query); 

それは、このエラーを与える:

'ObservableCollection' does not contain a definition for 'GetAwaiter' and no extension method 'GetAwaiter' accepting a first argument of type 'ObservableCollection' could be found (are you missing a using directive or an assembly reference?)

それはObservableCollectionを返していた場合にどのように検索asyncを作るのですか?ありがとう。

更新

_worker.DoWork += async (o, ea) => 
{ 
    SearchResults = await dataService 
     .SearchEmployees(selectedColumnValue, SearchValue); 
    IsSearching = false; 
}; 

そして、私は完全に_worker.RunWorkerCompletedブロックを削除:動作するようにビジーインジケータのために、私はこの変更をしなければなりませんでした。おそらくそれを行うためのより良い方法がありますが、これは私がそれを働かせる方法でした。

+1

あなたはこれをお読みくださいhttps://msdn.microsoft.com/en-us/library/hh191443.aspx – Will

答えて

2

いくつかのアプローチがあります。まず、データベースへのアクセスを同期させ、バックグラウンドスレッドで実行するだけです。 Task.RunBackgroundWorkerための近代的な交換があることに注意してください(私はblog series that draws parallels between the two持っている):

public async Task SearchEmployeesAsync() 
{ 
    var dataService = new EmployeeDataService(); 
    var selectedColumn = SelectedColumn; 
    var searchValue = searchValue; 

    IsSearching = true; 
    try 
    { 
    SearchResults = await Task.Run(() => dataService.SearchEmployees(selectedColumn, searchValue)); 
    } 
    finally 
    { 
    IsSearching = false; 
    } 
} 

を別の方法として、あなたはEF6を使用しているので、あなたは、すべてのバックグラウンドスレッドで周りのあなたのデータベースクエリ非同期ではなく混乱を行うことができます。

public async Task<ObservableCollection<EmployeeViewModel>> 
    SearchEmployeesAsync(string selectedColumn, string searchValue) 
{ 
    var paramEmployee = Expression.Parameter(typeof(Employee), "e"); 
    var comparison = Expression.Lambda<Func<Employee, bool>>(
    Expression.Equal(
     Expression.Property(paramEmployee, selectedColumn), 
     Expression.Constant(searchValue)), 
     paramEmployee).Compile(); 

    using (var context = new MyEntities()) 
    { 
    var query = (from e in context.Employees 
       .Where(comparison) 
       select new EmployeeViewModel 
       { 
        // Various EF model properties... 
       }); 
    var data = await query.ToListAsync(); 
    return new ObservableCollection<EmployeeViewModel>(data); 
    } 
} 

public async Task SearchEmployeesAsync() 
{ 
    var dataService = new EmployeeDataService(); 
    IsSearching = true; 
    try 
    { 
    SearchResults = await dataService.SearchEmployeesAsync(SelectedColumn, SearchValue); 
    } 
    finally 
    { 
    IsSearching = false; 
    } 
} 

BackgroundWorker.DoWork非同期です。それは "早期終了"を引き起こし、正常に例外を処理しないようにします。 BGWは単にasyncコードで動作するようには設計されていませんでした。

+0

ありがとう、@StephenCleary。 'query.ToListAsync()'の理由がありますか?それから新しいObservableCollectionを取得していますか? – Alex

+0

戻り値のないデリゲートメソッド名だった 'RelayCommand'に問題があります。 'SearchEmployeesRelayCommand = new RelayCommand(SearchEmployees);'この戻り値の型を 'void'から' Task'に変更するにはどうしたらいいですか? – Alex

+0

これは、値を返す 'RelayCommand'の問題を解決すると思います:http://stackoverflow.com/questions/2240042/commanding-in-mvvm-wpf-how-to-return-a-value – Alex

関連する問題