异步方法上的C#实体框架错误 [英] C# Entity Framework error on async methods
问题描述
我已经看到了,但是我遇到了另一个问题.
I have already seen this, but I am experiencing another problem.
我具有用于管理ASP.NET身份角色的服务类:
I have this service class for managing ASP.NET identity roles:
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);
}
}
根据此问题的建议,我使用这样的 CreateAsync
方法来避免使用LINQ <代码> foreach :
As suggested by this question, I use the CreateAsync
method like this to avoid using 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()
时,这会导致错误.
However, this results in an error when await this.PopulateRoles()
is executed.
实体框架:已经有一个与此命令相关联的打开的DataReader,必须首先将其关闭.
Entity Framework: There is already an open DataReader associated with this Command which must be closed first.
搜索此错误仅导致我建议在我的Select LINQ中添加 ToList()
.我该如何解决?
Searching for this error only leads me to a suggestion of adding a ToList()
in my Select LINQ. How can I fix it?
推荐答案
问题出在 RoleManager< T>
上,我们可以在内部给它一个单独的 DbContext
参见此处:>
The problem lays with the RoleManager<T>
which internally is given a single DbContext
as we can see 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
本身无法处理并发调用.另一种选择是在每个 foreach
和 await
内执行每个调用:
DbContext
itself can't handle concurrent calls. The alternative would be to execute each of the calls inside a foreach
and await
each one:
private async Task PopulateRoles()
{
var roles = new[] { "A", "B", "C", "D" };
foreach (var role in roles)
{
await _roleService.CreateAsync(new ApplicationRole(role));
}
}
这样,尽管您没有同时应用所有角色的好处,但您仍然可以利用IO调用的异步特性,而不是阻止同步调用.
This way, though you don't have the benefit of applying all roles concurrently, you do still take advantage of the async nature of the IO call, instead of a blocking synchronous call.
这篇关于异步方法上的C#实体框架错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!