-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Register a scoped DbContext automatically when using AddDbContextFactory #25164
Comments
We don't currently do this because the context instances injected will be disposed by D.I., while the factory returns instances that need to be disposed explicitly. So, to help this not be a pit-of-failure, we require registration of the factory explicitly if you want to use it. |
Is the following DI registration appropriate/correct? services.AddDbContextFactory<MyDbContext>((sp, options) =>
{
options.UseNpgsql("CONNECTIONSTRING");
}).AddScoped<MyDbContext>(p => p.GetRequiredService<IDbContextFactory<MyDbContext>>().CreateDbContext()); Controllers get the standard ctor MyDbContext injection (http request scoped, no dispose) and background services/blazor components get the IDbContextFactory injection (custom scope, requires dispose). Is it safe to assume that, in the above registration, that scoped instances of MyDbContext will be dispose once the scope is disposed? |
Split out from work on #25164 In some cases we still don't, but each case where we don't is commented as to why.
Results from design investigation:
|
Fixes #25164 Results from design investigation: * AddDbContext registers DbContextOptions as scoped by default. This cannot be consumed from the default singleton factory. Changing the lifetime of DbContextOptions is a breaking change. This prevents us from adding the factory automatically, since it will not work correctly in the default/normal case. * AddDbContextFactory can automatically add a scoped DbContext registration. This will depend on the singleton options added with the factory, which will work. This is the change we will make. * Applications that explicitly register a DbContext as well as using AddDbContextFactory will not be impacted, since we always TryAdd in our methods. * Applications that are already calling AddDbContextFactory first, and then also AddDbContext, would have the registration made by AddDbContext ignored, since AddDbContext uses TryAdd. This would be breaking for these applications. Therefore, if AddDbContextFactory has been called, and then AddDbContext is also called, AddDbContext will replace the registration made by AddDbContextFactory. This could also be breaking in corner cases, but is the best we can do if we want to implement this at all.
From #25440 (review):
Is there a downside to registering a factory as scoped in this case (in other words, always register the factory with the scope of the options)? This would ensure that the factory is consistently available in DI, without an extra gesture. |
It wouldn't be possible to inject it into a singleton then |
@davidfowl conversation happening in #25440, will answer there. |
Applications that need to inject the db context into background services (which are singletons) should be using the IDbContextFactory<TContext> instead of manually creating a scope and resolving the DbContext from it.
When I call services.AddDbContext<TContext> automagically add the supporting services to make injection of an IDbContextFactory work.
The text was updated successfully, but these errors were encountered: