Skip to content
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

Closed
davidfowl opened this issue Jun 28, 2021 · 6 comments · Fixed by #25440
Closed

Register a scoped DbContext automatically when using AddDbContextFactory #25164

davidfowl opened this issue Jun 28, 2021 · 6 comments · Fixed by #25440
Labels
area-dbcontext closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@davidfowl
Copy link
Member

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.

@ajcvickers
Copy link
Member

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.

@vflame
Copy link

vflame commented Jun 30, 2021

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?

@AndriySvyryd AndriySvyryd added this to the 6.0.0 milestone Jul 12, 2021
ajcvickers added a commit that referenced this issue Aug 5, 2021
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.
@ajcvickers
Copy link
Member

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.

ajcvickers added a commit that referenced this issue Aug 6, 2021
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.
@ajcvickers ajcvickers added area-dbcontext closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. and removed needs-design customer-reported labels Aug 6, 2021
@roji
Copy link
Member

roji commented Aug 6, 2021

From #25440 (review):

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.

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.

@davidfowl
Copy link
Member Author

It wouldn't be possible to inject it into a singleton then

@roji
Copy link
Member

roji commented Aug 6, 2021

@davidfowl conversation happening in #25440, will answer there.

@ajcvickers ajcvickers changed the title Add IDbContextFactory<T> when calling AddDbContext Register a scoped DbContext automatically when using AddDbContextFactory Aug 11, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0, 6.0.0-rc1 Aug 12, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0-rc1, 6.0.0 Nov 8, 2021
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dbcontext closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants