【问题标题】:C# Entity Framework error on async methods异步方法上的 C# Entity Framework 错误
【发布时间】:2015-02-24 08:43:13
【问题描述】:

我已经看到了,但是我遇到了另一个问题。

我有这个用于管理 ASP.NET 身份角色的服务类:

public class RoleService : IRoleService
{
    private readonly RoleManager<ApplicationRole> _roleManager;

    public RoleService(RoleManager<ApplicationRole> roleManager)
    {
        this._roleManager = roleManager;
    }

    public async Task<IdentityResult> CreateAsync(ApplicationRole role)
    {
        return await this._roleManager.CreateAsync(role);
    }
}

按照this question的建议,我使用CreateAsync这样的方法来避免使用LINQ foreach

private async Task PopulateRoles()
{
     var roles = new[] { "A", "B", "C", "D" };

     // Used LINQ foreach previously but I coded this way instead to follow the related questions's answer
     var tasks = roles.Select(role =>
                           this._roleService.CreateAsync(new ApplicationRole(role)))
                      .ToList();

     await Task.WhenAll(tasks);
}

但是,这会在执行await this.PopulateRoles() 时导致错误。

实体框架:已经有一个打开的 DataReader 与此命令关联,必须先关闭。

搜索此错误只会导致我建议在我的 Select LINQ 中添加 ToList()。我该如何解决?

【问题讨论】:

  • RoleManager 实例不是线程安全的。多个CreateAsync 任务正在争夺同一个连接。您应该以传统的串行方式执行此操作。
  • 我会以同步方式创建角色吗?
  • 是的,这就是我的建议。
  • 感谢您的建议。我会等待其他人的评论(如果还有的话:D)
  • 如果您只有一个RoleManager 实例,您将无法同时创建多个用户。这是一个问题吗?你能简单地使用foreachawait 来迭代它们吗?

标签: c# .net entity-framework asynchronous async-await


【解决方案1】:

问题在于RoleManager&lt;T&gt;,它在内部被赋予了一个DbContext,我们可以看到here

public class RoleStore<TRole, TContext, TKey> : 
        IQueryableRoleStore<TRole>, 
        IRoleClaimStore<TRole>
        where TRole : IdentityRole<TKey>
        where TKey : IEquatable<TKey>
        where TContext : DbContext
{
    public RoleStore(TContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        Context = context;
    }
}

DbContext 本身无法处理并发调用。另一种方法是在 foreachawait 中执行每个调用:

private async Task PopulateRoles()
{
     var roles = new[] { "A", "B", "C", "D" };

     foreach (var role in roles)
     {
         await _roleService.CreateAsync(new ApplicationRole(role));
     }
}

这样,虽然您没有同时应用所有角色的好处,但您仍然可以利用 IO 调用的异步特性,而不是阻塞同步调用。

【讨论】:

    猜你喜欢
    • 2017-03-18
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 2020-12-15
    • 2018-10-05
    • 2015-03-23
    相关资源
    最近更新 更多