I'm trying to use the new DbContextFactory
pattern discussed in the DbContext configuration section of the EF Core docs.
I've got the DbContextFactory
up and running successfully in my Blazor app, but I want to retain the option to inject instances of DbContext
directly in order to keep my existing code working.
However, when I try to do that, I'm getting an error along the lines of:
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory
1[MyContext] Lifetime: Singleton ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory
1[MyContext]': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions1[MyContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory
1[MyContext]'.) ---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory1[MyContext] Lifetime: Singleton ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory
1[MyContext]': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions1[MyContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory
1[MyContext]'. ---> System.InvalidOperationException: Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions1[MyContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory
1[MyContext]'.
I also managed to get this error at one point while experimenting:
Cannot resolve scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[MyContext]' from root provider.
Is it theoretically possible to use both AddDbContext
and AddDbContextFactory
together?
It is, it's all about understanding the lifetimes of the various elements in play and getting those set correctly.
By default the
DbContextFactory
created by theAddDbContextFactory()
extension method has a Singleton lifespan. If you use theAddDbContext()
extension method with it's default settings it will create aDbContextOptions
with aScoped
lifespan (see the source-code here), and as aSingleton
can't use something with a shorterScoped
lifespan, an error is thrown.To get round this, we need to change the lifespan of the
DbContextOptions
to also be 'Singleton'. This can be done using by explicitly setting the scope of theDbContextOptions
parameter ofAddDbContext()
There's a really good discussion of this on the EF core GitHub repository starting here. It's also well worth having a look at the source-code for
DbContextFactory
here.Alternatively, you can also change the lifetime of the
DbContextFactory
by setting the ServiceLifetime parameter in the constructor:The options should be configured exactly as you would for a normal DbContext as those are the options that will be set on the DbContext the factory creates.