繁体   English   中英

运行使用EF Core的并行异步任务时发生异常

[英]Exception when running parallel async tasks that use EF Core

我试图了解当数据库上下文已注入到类中时如何处理使用实体框架的并行异步任务。

我有一个显示大量总计的仪表板,而我想做的是运行并行返回这些总计的方法。 目前,我有一些看起来像这样的代码:

public class KpiRepository : IKpiRepository
{
    private readonly kpiContext _context;

    public KpiRepository(kpiContext context)
    {
        _context = context;
    }

    public Task<int> NonCompliantTotalCountAsync()
    {
        return _context.vw_SearchData
            .CountAsync(x => x.NonComplianceDate < DateTime.Today || x.DateDueOutOfService < DateTime.Today);
    }

    public Task<int> NonCompliantInNextWeekCountAsync()
    {
        return NonCompliantBetweenNowAndDateCountAsync(DateTime.Today.AddDays(7));
    }

    public Task<int> NonCompliantInNextMonthCountAsync()
    {
        return NonCompliantBetweenNowAndDateCountAsync(DateTime.Today.AddMonths(1));
    }

    private Task<int> NonCompliantBetweenNowAndDateCountAsync(DateTime endDate)
    {
        return _context.vw_SearchData
            .CountAsync(x => (x.NonComplianceDate >= DateTime.Today && x.NonComplianceDate <= endDate)
                || (x.DateDueOutOfService >= DateTime.Today && x.DateDueOutOfService <= endDate));
    }

    var taskNonCompliantInNextWeekCountAsync = NonCompliantInNextWeekCountAsync();
    var taskNonCompliantInNextMonthCountAsync = NonCompliantInNextMonthCountAsync();  

    Task.WaitAll(
        taskNonCompliantInNextWeekCountAsync,
        taskNonCompliantInNextMonthCountAsync
    );

    data.NonCompliantInNextWeekCount= taskNonCompliantInNextWeekCountAsync.Result;
    data.NonCompliantInNextMonthCount= taskNonCompliantInNextMonthCountAsync.Result;

当我运行该代码时,我从Task.WaitAll行收到此错误:

InvalidOperationException:连接未关闭。 连接的当前状态为连接中。

经过一番阅读后,我意识到Entity Framework不是线程安全的 ,因此,我猜测造成异常的原因是,在运行每个任务时,它们都使用相同的上下文实例,这导致EF引发例外?

因此,解决方案似乎是为每个任务创建上下文的新实例,但是我使用的是依赖注入,因此默认情况下,上下文实例的作用域为服务器请求的生存期(我认为)。

那么,以上理解是否正确?如果是,那么为我的每个任务获取新上下文而不是重用现有任务的解决方案是否正确? 我该怎么做?

我添加了一个工厂类来创建我的上下文的新实例:

   public class KpiContextFactory: IKpiContextFactory
    {
        private string _connection = @"Server=.\SQL2008EXP;Database=kpiDb;Trusted_Connection=True;";

        public KpiContext GetNewContext()
        {
            var optionsBuilder = new DbContextOptionsBuilder<KpiContext>();
            optionsBuilder.UseSqlServer(_connection);

            return new KpiContext(optionsBuilder.Options);
        }
    }

现在,我只是注入该工厂而不是上下文本身,然后调用_kpiContextFactory.GetNewContext().[method]而不是_context.[method] 这似乎很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM