c# - 运行使用 EF Core 的并行异步任务时出现异常

标签 c# dependency-injection asp.net-core async-await entity-framework-core

我试图了解当数据库上下文已注入(inject)类时如何处理使用 Entity Framework 的并行异步任务。

我有一个显示多个总计的仪表板,我想做的是并行运行返回这些总计的方法。目前我有一些代码如下所示:

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: The connection was not closed. The connection's current state is connecting.

some reading之后我意识到Entity Framework is not thread safe ,所以,我猜测导致异常的原因是,当我的每个任务运行时,它们都使用相同的上下文实例,这导致 EF 引发异常?

因此,解决方案似乎是为每个任务创建一个新的上下文实例,但我正在使用依赖注入(inject),因此默认情况下我的上下文实例的范围仅限于服务器请求的生命周期(我认为)。

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

最佳答案

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

   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);
        }
    }

现在我只是注入(inject)该工厂而不是上下文本身,然后调用 _kpiContextFactory.GetNewContext().[method] 而不是 _context.[method]。看起来效果很好。

关于c# - 运行使用 EF Core 的并行异步任务时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43250357/

相关文章:

c# - .NET 中 ArgumentException.Message 的本地化

c# - mvc core中注册DI时如何访问ISession

dependency-injection - "reify"在依赖注入(inject)的上下文中到底意味着什么

asp.net-core - 在 VS 2017 RC 中创建 ASP.NET Core Web App 时缺少 web.config?

c# - 如何使 IEnumerable 和 IQueryable 异步?

c# - 从 Json.NET 中的 JToken 隐式转换

c# - 如何使 WPF 数据网格的第一行成为自动添加新行的行

c# - 如何修复对象旋转并使其在 Vuforia 中垂直?

c# - 简单注入(inject)器依赖解析错误 - 无法加载文件或程序集 System.Web.Http

c# - ASP.NET Core Identity,如何覆盖 IdentityRole 名称唯一索引?我想存储关于租户的重复名称