【问题标题】:How to perform multiple operations concurrently on DbContext?如何在 DbContext 上同时执行多个操作?
【发布时间】:2022-06-13 20:47:50
【问题描述】:

我正在运行以下后台服务:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await Task.Run(async () =>
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    using (var scope = _scopeFactory.CreateScope())
                    {
                        DataContext dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
                        var tasks = new List<Task>();
                        tasks.Add(siteA.ProcessSchedule(SportLeagues.MLB, logger, dbContext));
                        tasks.Add(siteB.ProcessSchedule(SportLeagues.MLB, logger, dbContext));
                        //....more of same task
                        await Task.WhenAll(tasks);
                        await dbContext.SaveChangesAsync();
                        await Task.Delay(0, stoppingToken);
                    }
                }
            });
        }

我经常收到这个错误

System.InvalidOperationException: 
    A second operation was started on this context instance before a previous operation completed.

我可以重构并为每个任务创建一个dbContext,但是如果可能的话,我更愿意使用单个 dbContext。

我还尝试将我的 dbContext 添加为瞬态:

builder.Services.AddDbContext<DataContext>(options =>
{
    options.UseInMemoryDatabase("db");
}, ServiceLifetime.Transient);

但这并没有帮助。我是否以不正确的方式创建了我的 dbContext?或者是为每个任务创建一个新的dbContext 的最佳方法?对于更多上下文,这是一个不断运行的后台任务,需要一秒钟才能完成,它将有大约 20 个任务。每秒创建和销毁 20 个 dbContext 以及必须进行 20 个 dbContext 保存听起来效率很低。

【问题讨论】:

  • 如果您连续进行这项工作,您不需要创建和销毁上下文,您可以只保留它们并重新使用它们。是的,每个并行运行的任务都需要一个,它们不是线程安全的。

标签: c# asp.net .net entity-framework asp.net-core


猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-31
  • 2017-04-03
  • 2013-08-27
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多