簡體   English   中英

在前一個操作完成之前,在此上下文上啟動了第二個操作 Asp.net EF Core

[英]A second operation started on this context before a previous operation completed Asp.net EF Core

我有一個小問題,我一直在使用頁面上的視圖組件,並且不斷收到以下內容。 我正在使用 asp.net 核心 3.1 和 ef 核心 3.1

處理請求時數據庫操作失敗。 InvalidOperationException:在前一個操作完成之前在此上下文上啟動了第二個操作。 這通常是由使用相同 DbContext 實例的不同線程引起的。 有關如何避免 DbContext 線程問題的詳細信息,請參閱https://go.microsoft.com/fwlink/?linkid=2097913 MISDBContext 有待處理的 model 更改在 Visual Studio 中,使用 Package 管理器控制台為這些更改構建新遷移並將它們應用到數據庫:

PM> Add-Migration [migration name] PM> Update-Database 或者,您可以構建一個新的遷移並從項目目錄的命令提示符應用它:

dotnet ef 遷移添加 [遷移名稱] dotnet ef 數據庫更新

我已經檢查了 SO,它建議您將以下內容添加到您的 class 現在我認為我根本不需要第二個上下文是什么導致了我的問題。 我添加了行

ServiceLifetime.Transient

顯然,上面的行允許更多的並發連接到上下文。

services.AddDbContext<MISDBContext>
 (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);

services.AddDbContext<ApplicationDbContext>(options =>
 options.UseSqlServer(
 Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);            

這是我的視圖組件的典型布局,我認為實際上它可能是導致問題的原因,因為我試圖與上下文同時訪問用戶存儲。

 private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
    public async Task<Guid> GetCurrentTennantId() {
        ApplicationUser usr = await GetCurrentUserAsync();
        TempData["TeannantId"] = usr?.Id;
        Guid.TryParse(usr?.Id, out Guid resultTennantId);
        return resultTennantId;
    }
    private Task<List<ApplicationUser>> GetItemsAsync() {
        string currentUser =  GetCurrentTennantId().Result.ToString();
        var excludeCurrentUser= _userManager.Users.Where(w => w.Id != currentUser).ToListAsync();
        return excludeCurrentUser;
    }
}

顯然,上面的行允許更多的並發連接到上下文。

不; 它為每個請求創建一個新的上下文。 每個上下文一次只能用於一個操作。 因此,例如,如果您的上下文以前是 singleton,那么一次只有一個 HTTP 請求可以進行操作。

我認為實際上這可能是導致問題的原因,因為我試圖與上下文同時訪問用戶存儲。

此代碼本身不會導致問題,但如果此模式在您的代碼庫中重復出現,則可能會導致問題。

總之,對所有返回Task<T>的方法使用asyncawait ,除非該方法是 trivial 例如, GetCurrentUserAsync是微不足道的(它只是傳遞給另一個方法),所以可以省略async並在那里await GetItemsAsync絕對不是微不足道的,所以它應該使用asyncawait

private async Task<List<ApplicationUser>> GetItemsAsync() {
  string currentUser = (await GetCurrentTennantId()).ToString();
  return await _userManager.Users.Where(w => w.Id != currentUser).ToListAsync();
}

如果您在代碼庫中以類似的方式應用asyncawait ,您應該解決並發上下文問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM