1

这是使用 async 使用 foreach 循环的正确方法吗?有没有更好更有效的方法?IAsyncEnumerable?(忽略两个表可以连接在一起的事实,这是一个简单的例子)

public async Task<IList<ContactAndAccounts>> GetAll()
{
    var accounts = await _dbContext.Account.Where(x => x.Name == "Amazing").ToListAsync();

    foreach(var account in accounts)
    {
           accounts.Contacts = await GetContact(account.Id);
    }

    return accounts;
}

public async Task<IList<contact>> GetContact(Guid id)
{
    return await _dbContext.Contact.Where(x => x.AccountLinkId = id).ToListAsync();
}
4

3 回答 3

4

我同意Johnathan Barclay 的回答,但会说从数据库的角度来看,您可能会发现执行单个查询大查询比执行大量小查询更快。

执行一个查询并传入所有 id 通常比多个单独的查询便宜。

public async Task<IList<ContactAndAccounts>> GetAll()
{
    var accounts = await _dbContext.Account.Where(x => x.Name == "Amazing").ToListAsync();

    var contacts = await GetContacts(accounts.Select(o => o.Id));

    // Map contacts to accounts in memory

    return accounts;
}

public async Task<IList<contact>> GetContacts(List<Guid> ids)
{
    return await _dbContext.Contact.Where(x => ids.Contain(x.AccountLinkId)).ToListAsync();
}
于 2020-01-30T11:13:37.157 回答
0

这绝对不是最有效的方法。

每个都会await导致循环暂停,直到Task完成。

您希望允许所有任务同时运行:

public async Task<IList<ContactAndAccounts>> GetAll()
{
    var accounts = await _dbContext.Account.Where(x => x.Name == "Amazing").ToListAsync();

    await Task.WhenAll(accounts.Select(async account => 
    {
        accounts.Contact = await GetContact(account.Id);
    }));

    return accounts;
}

Select将为每个项目产生一个Task,可以通过等待Task.WhenAll

于 2020-01-30T11:10:35.587 回答
-2

有没有更好更有效的方法?IAsyncEnumerable?

是的!更改签名并替换accounts.Contacts = await GetContact(account.Id);yield return await GetContract(account.Id).

于 2020-01-30T11:16:11.983 回答