使用实体框架的异步操作

本文关键字:异步操作 框架 实体 | 更新日期: 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被证明是徒劳的,因为它似乎从未返回值

正如我在博客上所描述的,这种死锁最常见的原因是调用堆栈中更靠上的代码阻塞了任务(通常是通过调用WaitResult)。最正确的解决方案是将那些阻塞调用改为使用await