【问题标题】:ASP.NET Core Task.WhenAll - A second operation started on this context before a previous operation completedASP.NET Core Task.WhenAll - 在前一个操作完成之前在此上下文上启动了第二个操作
【发布时间】:2020-09-30 06:35:44
【问题描述】:

我开始尝试将我的数据库查询转换为异步的,但我真的不明白如何正确地做到这一点。

我现在收到错误:

在前一个操作完成之前,在此上下文中启动了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的。有关如何避免 DbContext 线程问题的更多信息

public async Task<IList<MyObject>> GetAll(MyContext context)
    {
        
   return (await Task.WhenAll(
    MethodA(context), MethodB(context)))
    .SelectMany(e => e)
    .ToList();
}

 private async Task<IList<MyObject>> MethodA(MyContext context)
    {
    
    
 return await context.MyThings.Include(x => x.Stuff)
    
 //full query removed for readability 
.ToListAsync();
    
}

 private async Task<IList<MyObject>> MethodB(MyContext context)
    {
    
    
 return await context.MyThings.Include(x => x.Stuff)
    
 //full query removed for readability 
.ToListAsync();
    
}

index.cs:

public Task<IList<MyObject>> MyDBList  { get; set; }

public void OnGet()
    {
    
        MyDBList = _myInterface.GetAll_context);

}

索引.cshml


     @foreach (var x in Model.MyDBList)
    {
<p>x.ID</p>
}

我厌倦了使 dbcontext 瞬态,但它没有任何区别。我还担心它会破坏我更新数据库中条目的许多其他代码。

我可以看到错误发生的原因,我在同一个上下文中运行两个查询,但我不知道如何修复它。

谁能给点建议?

【问题讨论】:

  • 异常说的是,DbContext 不是线程安全的。您可以在多个线程中使用它,无论是否是瞬态的。
  • 对不起,我不明白你的意思。我明白为什么会出现错误,但我不知道如何强制它使用自己的 DBContext。

标签: entity-framework asp.net-core-3.1


【解决方案1】:

我可以看到错误发生的原因,我在同一个上下文中运行两个查询,但我不知道如何修复它。

修复它的最简单方法是一次只运行一个查询:

public async Task<IList<MyObject>> GetAll(MyContext context)
{
  var resultsA = await MethodA(context);
  var resultsB = await MethodB(context);
  return resultsA.Concat(resultsB).ToList();
}

更好的是,重构MethodAMethodB,以便只向数据库发送一个查询。

【讨论】:

  • 这是我最初的想法,但建议我尝试 Task.WhenAll。这给了我错误“无法访问已处置的对象”。我实际上有大约 8 个复杂的查询,我无法将它们全部合二为一。
  • 如果您的子查询是IQueryable,组合查询通常会更容易。如果您不想合并查询,请像我的回答一样依次进行。如果您想同时运行它们(并且仍然不合并它们),那么您需要创建多个数据库上下文,每个查询一个。
  • 您的回答给了我错误“无法访问已处置的对象”?我不知道如何创建多个 dbcontexts?我试图使用'using (var context = new MyContext())',但我似乎无法从我的 appsettings.json 传递连接字符串。我真的被困住了,因为我找到的每个解决方案似乎都有更多问题。
  • 处理问题可能是由于依赖注入设置不正确造成的。如果你想要多个数据库上下文,最简单的方法可能是编写自己的数据库上下文工厂。
  • 我的设置只是 services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("MyDatabase"), providerOptions => providerOptions.EnableRetryOnFailure()));在启动中。不幸的是,我在 ASP.NET 方面的知识并不先进,而且我没有可以向任何人学习的人。我可能不得不回溯并停止使用异步,直到我有更多时间玩它..
猜你喜欢
  • 2020-03-13
  • 2018-11-07
  • 1970-01-01
  • 2020-11-06
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
相关资源
最近更新 更多