c# - 在前一个操作完成之前,在此上下文上启动了第二个操作 Asp.net EF Core
问题描述
我有一个小问题,我一直在使用页面上的视图组件,并且不断收到以下内容。我正在使用 asp.net core 3.1 和 ef core 3.1
处理请求时数据库操作失败。InvalidOperationException:在前一个操作完成之前在此上下文上启动了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的。有关如何避免 DbContext 线程问题的更多信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2097913。MISDBContext 有待处理的模型更改 在 Visual Studio 中,使用包管理器控制台为这些更改构建新的迁移并将它们应用到数据库:
PM> Add-Migration [migration name] PM> Update-Database 或者,您可以构建一个新的迁移并从项目目录的命令提示符应用它:
dotnet ef 迁移添加 [迁移名称] dotnet ef 数据库更新
我已经检查了 SO,它建议您现在将以下内容添加到您的课程中,我认为我完全不需要第二个上下文是正确的,这是导致我的问题的原因。我添加了行
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;
}
}
解决方案
显然,上面的行允许更多的并发连接到上下文。
不; 它为每个请求创建一个新的上下文。每个上下文一次只能用于一个操作。因此,例如,如果您的上下文以前是单例的,那么一次只有一个 HTTP 请求可以进行操作。
我认为实际上这可能是导致问题的原因,因为我试图与上下文同时访问用户存储。
此代码本身不会导致问题,但如果此模式在您的代码库中重复出现,则可能会导致问题。
总之,对所有返回方法使用async
and ,除非该方法是 trivialawait
Task<T>
。例如,GetCurrentUserAsync
这是微不足道的(它只是传递给另一种方法),所以可以在那里async
省略await
。GetItemsAsync
绝对不是微不足道的,所以它应该使用async
and await
:
private async Task<List<ApplicationUser>> GetItemsAsync() {
string currentUser = (await GetCurrentTennantId()).ToString();
return await _userManager.Users.Where(w => w.Id != currentUser).ToListAsync();
}
如果您以类似的方式在您的代码库中应用,您应该解决并发上下文问题async
。await
推荐阅读
- c# - How to fix the display in DataGriView?
- r - Nested loop for regression over several columns in R
- xml - Understanding Various XML-related specs
- python - Use DataFrame to add values until certain amount, then store the remainder in a list
- openssl - Unable to redeploy the certificates post-expiry in openshift 3.11
- python - Complete a partial mesh and make it watetight
- sql - 在另一个表中查找与值最接近的匹配项
- ios - Value of type 'AuthDataResult' has no member 'uid' problem
- neo4j - Custom resolver with @cypher schema directive do not accept Date as an Input - GRANDStack
- c - Is there a way of limiting scanf in C?