Recently I ran into a nasty startup error after registering both AddDbContext and AddDbContextFactory for the same DbContext in an ASP.NET Core project:
System.AggregateException: 'Some services are not able to be constructed'
System.InvalidOperationException: 'Error while validating the service descriptor
'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory`1[StartStopLijsten.ApiService.Data.StartStopDbContext]
Lifetime: Singleton
ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory`1[StartStopLijsten.ApiService.Data.StartStopDbContext]':
Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[StartStopLijsten.ApiService.Data.StartStopDbContext]'
from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[StartStopLijsten.ApiService.Data.StartStopDbContext]'.'
The app refuses to start, and although the message is clear why it refuses to start, it doesn't make it obvious how to fix it.
The cause
AddDbContext gives you a scoped DbContext, injected directly wherever you need it. AddDbContextFactory instead registers an IDbContextFactory<TContext> as a singleton, so you can create short-lived context instances yourself — useful in Blazor components, background services, or anywhere the request-scoped lifetime doesn't fit.
Nothing wrong with wanting both in the same project. The problem is what happens under the hood when you register them together without thinking about lifetimes.
AddDbContext registers DbContextOptions<TContext> with a scoped lifetime by default. AddDbContextFactory registers IDbContextFactory<TContext> as a singleton. A singleton can't depend on a scoped service. That's exactly what the validation error is telling us, just buried under a lot of generic type names.
The fix
Tell AddDbContext to register its options as a singleton too:
services.AddDbContext<StartStopDbContext>(options =>
options.UseSqlServer(YourSqlConnection),
optionsLifetime: ServiceLifetime.Singleton);
Remark: this only changes the lifetime of DbContextOptions<TContext>, not the DbContext itself. Your scoped AddDbContext registration still hands out a scoped context per request. You're just aligning the options lifetime with what AddDbContextFactory needs.
Up to the next problem…