[英]asp.net core A second operation started on this context before a previous operation completed
[英]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>
的方法使用async
和await
,除非该方法是 trivial 。 例如, GetCurrentUserAsync
是微不足道的(它只是传递给另一个方法),所以可以省略async
并在那里await
。 GetItemsAsync
绝对不是微不足道的,所以它应该使用async
和await
:
private async Task<List<ApplicationUser>> GetItemsAsync() {
string currentUser = (await GetCurrentTennantId()).ToString();
return await _userManager.Users.Where(w => w.Id != currentUser).ToListAsync();
}
如果您在代码库中以类似的方式应用async
和await
,您应该解决并发上下文问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.