DbContextScope
DbContextScope copied to clipboard
Need way to disable disposing of DbContext when root DbContextScope is disposed
The way this library works now is that the DbContext
instances are disposed when the root DbContextScope
is disposed.
I'm using this library in an OData Web Api project. The behaviour of disposing DbContext
instances is causing problems with the OData pipeline because OData expects the DbContext
to be open until very late in the Web Api pipeline. The only way of keeping the DbContext
open is to create the DbContextScope
very early in the process in the Owin middleware, but I didn't want to do that because I want to have a readonly or readwrite scope depending on the requested controller action, and this is not yet known at the Owin stage.
So I had to resort to trickery to keep the DbContext
from being disposed right away, which was to override the Dispose(bool disposing)
method of the DbContext
and add another ManualDispose()
method to dispose of the DbContext
at a later time.
It would be nice if it were possible to create a DbContextScope
with the option to disable auto disposing of the DbContext
instances.
Or does someone have another suggestion to tackle this issue?
Can you just not dispose the DbContextScope?
Jaap-van-Hengstum, please, share your decision, if your figured it out. I'm really on the same page with about this question.
I play with .NET Core and native DI for my Web API. Tried many approches with DbContextScope
, IAmbientContextLocator
and their lifetimes. As I understood correctly, DbContextScope should be Transient and AmbientContextLocator - Singleton. But the problem exactly the same - DbContextScope
kills DbContext
everytime.
In short words, the answer is: register your DbContext as Transient lifetime.
And ... the long story:
In .NET Core 1.1 you register your DbContexts by default in Scoped lifetime, like this:
services.AddDbContext<AttendeeContext>(options => options.UseSqlServer(connectionString)
So, how DbContextScope does his job (as long, as I debugged sources):
- in each new scope, (like it usually recommends:
using (var dbScope = _factory.Create()) { ... }
) the new collection of DbContexts initialized - not previously initialized DbContexts in the current scope of whole web request. - when the
dbScope
code block ends,using
statement callsDispose
for your DbContextScope and that means exact disposing of all your existing collection of DbContexts. - What does it mean for lifetime of DbContext in scope of lifetime of whole Web request? -- it means, that you manually have killed DbContext somewhere in the middle of living your Web request, and DbContext becomes unavailable for next calls inside still alive Web Request.
The solution is to allow your serviceProvider to recreate DbContext for each request during Scoped lifetime of your Web request:
services.AddDbContext<AttendeeContext>(options => options.UseSqlServer(connectionString, ServiceLifeTime.Transient)
And by the way, I also registered IDbContextScopeFactory
as Singleton lifetime.