【发布时间】:2020-03-29 21:37:59
【问题描述】:
我有一个返回 ViewModel 异步的方法:
public async Task<CardUserBindingViewModel> GetCardUserBindingViewModel(int cardId)
{
/// ... creditStatus, remainCreditDays
return await Task.Run(() => new CardUserBindingViewModel
{
Id = card.Id,
SerialNumber = card.SerialNumber,
PurchaseDate = card.PurchaseDate,
Cost = card.Cost,
CreditStatus = creditStatus,
RemainCreditDays = remainCreditDays.ToString(),
Profile = null
});
}
并想将其用作 Select 表达式,例如:
public async Task<IEnumerable<CardUserBindingViewModel>> FindByUserId(int userId)
{
return await Task.Run(() =>
{
return _context.Card
.Where(c => c.UserAccountId.Equals(userId))
.AsEnumerable()
.Select(async c => await GetCardUserBindingViewModel(c.Id));
});
}
错误是:
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<API.Models.CardUserBindingViewModel>>' to
'System.Collections.Generic.IEnumerable<API.Models.CardUserBindingViewModel>'. An explicit conversion exists (are you missing a cast?)
是否可以防止在 Select 扩展中再次创建 ViewModel?
【问题讨论】:
-
所有
Task.Run是怎么回事?在这两种方法中,但特别是在第一种方法中……创建新视图模型时您没有做任何工作,为什么将其包装在任务中?在第二种方法中也是值得怀疑的,EF Core 有异步操作符(即ToListAsync),你应该使用它来代替/结合 -
如果我使用它就可以了:
.Select(async c => await GetCardUserBindingViewModel(c.Id)).Select(x => x.Result);让我知道它是否适合你,我可以像回答一样添加它。 -
@Sajid 无效,出现一个或多个错误时引发新错误。 (已经有一个打开的 DataReader 与此命令关联,必须先关闭。)
-
@pinkfloydx33 谢谢,但这两种方法有更多参考
-
我认为您可以使用
Task.WhenAll并将查询分隔为两个子查询,如以下代码:var cards = context.Card.Where(c =>c.UserAccountId.Equals(userId)).AsEnumerable();return await Task.WhenAll(cards.Select(c => GetCardUserBindingViewModel(c.Id)))
标签: c# linq entity-framework-core