如何在lambda中选择期间等待

RND*_*hts 1 c# lambda async-await

我正在尝试使用实体框架从表中执行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;
            }
Run Code Online (Sandbox Code Playgroud)

我知道Linq对await/async的支持有限,我在StackOverflow上看了几个其他的例子,其中异步部分被移动到一个单独的循环中,例如:

如何等待Linq查询中的方法

T[] data = await Task.WhenAll(contacts.Select(c => LoadDataAsync(c)));
Run Code Online (Sandbox Code Playgroud)

但是,这种方法不会让我更新被称为"c"的对象,除非我通过引用传递异步方法不允许的引用.

有人可以解释正确填充名称属性的最有效方法吗?

Ste*_*ary 5

您只需要在LINQ-to-Objects中进行辅助查找,而不是LINQ-to-Entities:

// 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);
Run Code Online (Sandbox Code Playgroud)

我们的想法是将尽可能多的逻辑推入最初的LINQ-to-Entities查询,包括过滤和投影.然后你执行它(ToListAsync).

然后,您获取数据库结果并执行辅助查找.