我熟悉編寫高響應度的ASP.NET MVC應用程序的過程,我們在其中加載初始頁面數據,然後觸發多個AJAX調用以加載頁面的“輔助”數據。因此,在後台,這些AJAX請求幾乎都同時到達了Web服務器,並從我們的SQL DB中提取數據。
我設想使用Blazor應用程序執行非常類似的操作。因此,我們將向頁面加載一些數據,然後讓多個組件在頁面上顯示並包含其他數據;這些組件的加載可以通過用戶操作或頁面上的某些其他事件來初始化。
那就是我看到的一個問題:事件處理程序對剃刀頁面上各個組件觸發的事件都做出了非常好的反應,然後它們都擊中了我們的DataService(注入到頁面中),然後導致很多線程擊中了Entity框架的上下文。
這是不允許的-任意時刻只能有一個線程調用上下文。
為了解決這個問題,我可以使用SemaphoreSlip(1,1)鎖定Context,以確保在任何時候都只有一個線程可以訪問,但這對我來說有點瓶頸。當然,鎖定上下文不是Microsoft期望我們做的事情。
我在這裡想念什麼?
我正在使用Blazor-Server,.NET Core 3.1 / EF Core 3.1。在我的應用程序啟動時,我正在設置EF上下文和DI服務:
services.AddDbContext<MyContext>();
services.AddScoped<MyService>();
上下文被注入到服務的構造函數中(按照Microsoft的Blazor示例),服務被注入到Page中。
您可以嘗試為每個請求創建一個新範圍:
public class MyViewModel : INotifyPropertyChanged
{
protected readonly IServiceScopeFactory _ServiceScopeFactory;
public MyViewModel(IServiceScopeFactory serviceScopeFactory)
{
_ServiceScopeFactory = serviceScopeFactory;
}
public async Task<IEnumerable<Dto>> GetList(string s)
{
using (var scope = _ServiceScopeFactory.CreateScope())
{
var referenceContext = scope.ServiceProvider.GetService<MyContext>();
return await _myContext.Table1.where(....)....ToListAsync();
}
}
Daniel Roth(Blazor產品經理)在此談論將實體框架核心與Blazor結合使用
我解決了問題,但是我認為我已經失去了工作單位,因為現在我擁有多個dbContex:
構造函數:
private AppDbContext _db;
protected override void OnInitialized()
{
_db = new AppDbContext();
var query = _db.Set<Group>().AsQueryable();
}
然後我將其處置:
public void Dispose()
{
_db?.Dispose();
}