Avoid Entity Platform Mistakes with Multiple Tasks Running at the Same Time with the Same DbContext

I have a WebApi controller in a Dotnet Core project with an Entity Framework Core with Sqlite.

This code in action causes errors:

var t1 = _dbContext.Awesome.FirstOrDefaultAsync(a => [...]); var t2 = _dbContext.Bazinga.FirstOrDefaultAsync(b => [...]); var r1 = await t1; var r2 = await t2; 

Errors were:

  • Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory: Error: An exception occurred in the database, iterating the query results. System.ObjectDisposedException: secure handle closed

  • Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory: Error: An exception occurred in the database, iterating the query results. System.InvalidOperationException: ExecuteReader can only be when the connection is open.

Both errors tell me what happens to DbContext as a premature order (although not DbContext itself). DbContext is entered into the controllerโ€™s constructor using the Dotnet Core plumbing in the โ€œusual wayโ€, the configuration as shown below (from my Startup.cs ConfigureServices method body):

 services.AddDbContext<ApplicationContext>(options => options.UseSqlite(connectionString)); 

If I change the error by producing the code above, to something like:

 var r1 = await _dbContext.Awesome.FirstOrDefaultAsync(a => [...]); var r2 = await _dbContext.Bazinga.FirstOrDefaultAsync(b => [...]); 

... I did not see the errors mentioned, so the conclusion that the simultaneous execution of several tasks in one instance of my DbContext (introduced as described above) causes a problem. Obviously, this is unexpected.

Questions:

  • Am I coming to the right conclusion or is something else happening?
  • Can you determine why errors occur only occasionally?
  • Do you know any easy way to avoid the problem while doing parallel tasks on DbContext ?
+5
source share
1 answer

Unfortunately, you cannot do this.

From the EF Core Documentation

EF Core does not support multiple concurrent operations performed in the same context instance. You should always wait for the operation to complete before the next operation begins. This is usually done using the await keyword for each asynchronous operation.

Also from the EF 6 documentation

Thread safety

While thread safety will make async more useful, it is an orthogonal function. It is not clear that we could implement support for it in the most general case, given that EF interacts with a schedule consisting of user code to maintain state, and there are no easy ways to ensure that this code is also thread safe.

At this point, EF will detect if the developer is trying to perform two async operations at a time and quit.


A DbContext only supports one open data reader at any given time. If you want to run multiple simultaneous database queries, you will need multiple instances of DbContext , one for each parallel query.

How often an error occurs is a condition of the race. Just because you start 2 jobs one after another (without waiting) does not guarantee that the database will be deleted at the same time. Sometimes the execution time occurs in the queue, and in other cases, one task can end immediately, as the other task starts, so there is no conflict.

How to avoid this - do not do this, as it is not supported. Expect each of the DbContext calls, or use multiple instances of DbContext.

by request I mean any DB operation, including SELECT, UPDATE, DELETE, INSERT, ALTER, STORED PROCEDURE CALL, ETC

+5
source

Source: https://habr.com/ru/post/1266912/


All Articles