我试图了解当数据库上下文已注入(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/