[英]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.