Actually I started with Blazor
and EF Core
. At registering the DbContext
i get stucked. The DbContext
can be registerd with AddDbContext
or with AddDbContextFactory
. But what´s the difference?
builder.Services.AddDbContext<DataContext>(opt => opt.UseSqlServer("..."));
builder.Services.AddDbContextFactory<DataContext>(opt => opt.UseSqlServer("..."));
From docs i got following information:
AddDbContext
:
Use this method when using dependency injection ...
Entity Framework Core does not support multiple parallel operations being run on the same Microsoft.EntityFrameworkCore.DbContext instance. This includes both parallel execution of async queries and any explicit concurrent use from multiple threads.
AddDbContextFactory
:
Registering a factory is recommended for Blazor applications and other situations where the dependency injection scope is not aligned with the context lifetime...
For convenience, this method also registers the context type itself as a scoped service. This allows a context instance to be resolved from a dependency injection scope directly or created by the factory, as appropriate.
So can we globally say that if the program needs access to DbContext
from different threads or at the same time it is necessary to register the context with AddDbContextFactory
because when it gets created (e.g. in the controller) the liftime is set to scoped and so we every time get a new DbContext
?
private readonly DataContext _dbContext;
public BlogController(IDbContextFactory<DataContext> dbFactory)
{
// Will be created as SCOPED DbContext?
_dbContext = dbFactory.CreateDbContext();
}
Also i found a similar Question here. And there the lifetime within AddDbContext
and AddDbContextFactory
is set during registration. Or I´m missing something.
So my question generally is:
- When use
AddDbContextFactory
instead ofAddDbContext
? - What´s the lifetime difference from
DbContext
betweenDbContextFactory
andAddDbContext
? - Should I generally use
DbContextFactory
forBlazor
projects? - Is there a memory overhead when
DbContext
is created within ascoped
lifetime?
CodePudding user response:
Premise: We like the lifetime of a DbContext to be as short as possible.
For an HTTP server app we have the Scope of a Requets/Response cycle. That is ideal, problem solved: inject a Scoped DbContext.
For a Blazor Server app, just as with WinForms and WPF, we don't have such convenient Scopes. So we must manage the DbContext more directly.
You can use the lifetime of a Form (Page), with IDisposable and/or OwningComponentBase but that lifetime is usually too long.
So the burden shifts to the Repositories (and/or Services): they must manage the DbContext on a per-method basis. That is where the DbContextFactory comes in: You can simply inject the Factory but each method looks like:
void DoSomething()
{
using (var ctx = _factory.CreateContext())
{
...
}
}
A Blazor WebAssembly app will not use a DbContext directly, so the above mainly applies to Blazor Server.
CodePudding user response:
When use AddDbContextFactory instead of AddDbContext?
In Blazor always use the DbContextFactory. But having said that, I'm sure someone will come up with an exception!
What´s the lifetime difference from DbContext between DbContextFactory and AddDbContext?
The DbContextFactory manages the lifecyle of it's DBContexts. Applying the "unit of work" principle and the lifecycle is that of the unit of work. If you add the context directly to the DI Container, such as with AddDbContext
, then it lives for the lifetime of the DI Container.
Should I generally use DbContextFactory for Blazor projects?
Already answered above
Is there a memory overhead when DbContext is created within a scoped lifetime?
Of course. Memory is used by undisposed objects. A scoped DbContext lives for the lifetime of the DI Container. Dispose isn't called on objects within the container until the container itself is destroyed. It's why you never use Transient DbContexts. They aren't disposed until the session DI Container is destroyed.