2016-10-20 3 views
1

テーブルから新しいモデルにEntity Frameworkを使用してLambda Selectを実行しようとしていますが、非同期メソッドを呼び出して各インスタンスのプロパティを返す必要があります設定:ラムダでの選択中に待機する方法

await Task.WhenAll(_context.UserContacts.Where(uc => uc.UserId == user.Id).Select(async uc => new MailContact 
      { 
       Email = uc.Contact.Email, 
       UserId = uc.Contact.UserId, 
       ContactId = uc.Contact.Id, 
       Name = uc.Contact.UserId != null ? await _graphService.GetUserByIdAsync(uc.Contact.UserId) : null; 
      } 

私はLINQのは/非同期のawaitのための限定的なサポートを持っていることを理解し、私は非同期部分が別々のループに移動されStackOverflowの上の他のいくつかの例を、例えば見てきた:

How to await a method in a Linq query

T[] data = await Task.WhenAll(contacts.Select(c => LoadDataAsync(c))); 

しかし、非同期メソッドでは許可されていない参照渡し以外は、このメソッドは "c"と呼ばれるオブジェクトを更新しません。

nameプロパティを正しく設定する最も効率的な方法を説明できる人はいますか?

答えて

0

私はラッパー作成することによって、これを解決:私はあなたがTask.WhenAll(lookupTasksを)待つ `リターンを使用することを意図しているかもしれないと思う

Name = u.UserId != null ? await GetDisplayName(u.UserId) : null 
4

あなただけのLINQツーオブジェクトではなく、LINQツーエンティティで二次検索を実行する必要があります。

// LINQ-to-Entities 
var users = await _context.UserContacts 
    .Where(uc => uc.UserId == user.Id) 
    .Select(uc => new 
    { 
     uc.Contact.Email, 
     uc.Contact.UserId, 
     ContactId = uc.Contact.Id, 
    }) 
    .ToListAsync(); 

// LINQ-to-Objects 
var lookupTasks = users.Select(async u => new 
    { 
     u.Email, 
     u.UserId, 
     u.ContactId, 
     Name = u.UserId != null ? await _graphService.GetUserByIdAsync(u.UserId) : null; 
    }); 
return await Task.WhenAll(lookupTasks); 

アイデアは、あなたが最初のLINQツーエンティティクエリにできるだけ多くのロジックをプッシュしています、フィルタリングと投影を含む。その後、それを実行します(ToListAsync)。

次に、DB結果を取得し、セカンダリルックアップを実行します。

+0

;:

private async Task<string> GetDisplayName(string userId) { if (string.IsNullOrEmpty(userId)) return null; var contactUser = await _graphService.GetUserByIdAsync(userId); return contactUser.DisplayName; } 

とこれに割り当てを変更します'Not'はTask.WhenAll(tasks); ' –

+0

を待っています@MetroSmurf:修正しました! –

+0

そうだね。新しい動的プロパティにすべてのプロパティを再選択することはできません:) – RNDThoughts

関連する問題