Reputation: 3980
I have a small issue i keep getting I am using view components on a page and I keep getting the following. I am using asp.net core 3.1 and ef core 3.1
A database operation failed while processing the request. InvalidOperationException: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913. There are pending model changes for MISDBContext In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:
PM> Add-Migration [migration name] PM> Update-Database Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
dotnet ef migrations add [migration name] dotnet ef database update
I have checked on SO and it recommended that you add the following to your class now I am i right in thinking i dont need the second context at all is that what is causing the issue in my case. I added the line
ServiceLifetime.Transient
Apparently the above line allows for more concurrent connections to the context.
services.AddDbContext<MISDBContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);
This is the typical layout of my view component I think in fact it may be this one that is causing the issue cause im trying to access the user store at the same time as the context.
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;
}
}
Upvotes: 0
Views: 745
Reputation: 456457
Apparently the above line allows for more concurrent connections to the context.
No; it creates a new context for each request. Each context can only be used for one operation at a time. So, e.g., if your context was previously a singleton, then only one HTTP request could make an operation at a time.
I think in fact it may be this one that is causing the issue cause im trying to access the user store at the same time as the context.
This code by itself can't cause the problem, but if this pattern is repeated in your code base, then it could cause the problem.
In summary, use async
and await
for all Task<T>
-returning methods, unless the method is trivial. E.g., GetCurrentUserAsync
is trivial (it's just passing through to another method), so it's fine to elide async
and await
there. GetItemsAsync
is definitely not trivial, so it should be using async
and await
:
private async Task<List<ApplicationUser>> GetItemsAsync() {
string currentUser = (await GetCurrentTennantId()).ToString();
return await _userManager.Users.Where(w => w.Id != currentUser).ToListAsync();
}
If you apply async
and await
in a similar manner across your codebase, you should resolve the concurrent context issue.
Upvotes: 1