使用实体框架的异步操作
本文关键字:异步操作 框架 实体 | 更新日期: 2023-09-27 18:19:33
我正在开发一个应用程序,该应用程序需要接收对象列表,并根据数据库值验证它们的属性,以确保所有内容都是有效的。但是,可能有许多具有许多属性的对象需要验证。
我最初的想法是为每个验证操作创建一个助手方法,每个验证操作打开一个到数据库上下文的连接,执行它们所需的select语句,然后返回适当的数据。
foreach循环中的最后一个操作是等待所有操作,然后移动到下一个对象。
然而,我最初尝试使用FirstOrDefaultAsync被证明是徒劳的,因为它似乎从未返回值,而且它似乎与Linq-to-SQL不兼容。那么,我还有什么其他选项可以使这些助手方法异步呢?
我的主要方法看起来像这样:
public async Task<List<BulkUserResponse.VerifiedUser>> ValidateBulkUsers(BulkUserResponse userList)
{
var users = userList.UserList;
foreach (var user in users)
{
var userGlobalLogin = VerifyGlobalLogin(user.GlobalLogin);
// other variables and helper methods
await Task.WhenAll(userGlobalLogin);
user.GlobalLogin = userGlobalLogin.Result;
// other properties and helper method assignment
}
return users;
}
其中一个辅助方法看起来像这样:
public async Task<BulkUserResponse.GlobalLogin> VerifyGlobalLogin(BulkUserResponse.GlobalLogin login)
{
using (var context = new DbContext())
{
var userExists = await context.GlobalLogins.FirstOrDefaultAsync(n => n.LoginName == login.Value) == null;
login.Valid = userExists;
login.VerificationMessage = (userExists ? "" : "Login already exists.");
return login;
}
}
最初,辅助方法看起来像:
public async Task<BulkUserResponse.GlobalLogin> VerifyGlobalLogin(BulkUserResponse.GlobalLogin login)
{
using (var context = new DbContext())
{
var userExists = context.GlobalLogins.FirstOrDefault(n => n.LoginName == login.Value) == null;
login.Valid = userExists;
login.VerificationMessage = (userExists ? "" : "Login already exists.");
return login;
}
}
它似乎与Linq-to-SQL不兼容。
LINQ to SQL不支持异步查询。但是,如果你可以升级到实体框架,你可以使用它
我最初尝试使用FirstOrDefaultAsync被证明是徒劳的,因为它似乎从未返回值
正如我在博客上所描述的,这种死锁最常见的原因是调用堆栈中更靠上的代码阻塞了任务(通常是通过调用Wait
或Result
)。最正确的解决方案是将那些阻塞调用改为使用await
。