I am working on an AspNetCore 2.1 WebApi. I am using Microsoft.Extensions.DependencyInjection
, AspNetCore.Identity
, and EntityFrameworkCore
.
In my DI registrations, I am calling:
services.AddDbContext<IMyDbContext, MyDbContext>();
Good, right? Pass around the contract. But then I hit an exception that the Identity Manager classes (UserManager
, RoleManager
, etc.) cannot be respolved in the Dependency Injection container because the Identity Stores they use (UserStore
, RoleStore
, etc.) cannot resolve their DI parameter (MyDbContext
).
It all points to this line when setting up Identity:
builder.AddEntityFrameworkStores<MyDbContext>();
... which is puking since the Identity Stores are looking for the concrete context and it is not registered with DI. The extension is expecting a class
that it can resolve down to DbContext
- and I cannot add an implicit operator to the interface IMyDbContext
to give it an implicit cast the DI extension method could use.
All this has me performing a rather ugly DI registration:
services
.AddDbContext<IMyDbContext, MyDbContext>()
.AddDbContext<MyDbContext>();
My guess is that I could clean up the DI registration by rolling my own IServiceCollection
extension and/or custom Identity Stores - which really seems like overkill here as I otherwise have no need to go beyond the default built-in Identity Stores.
I also don't really want to remove the <interface, concrete>
context registration as that will trickle down to all my constructor injections, and just seems wrong.
Has anybody tackled this already and found a work-around? Or can anybody at least confirm/deny that the double (interface && concrete) context registration in the DI will not cause other issues?
Thanks in advance!
By default, when you call AddDbContext
, you register a scoped DbContext
instance. This means that anywhere within the handling of a single request, requesting said DbContext
via DI will give you the same instance. With the double registration you have, the DI system will give you a different instance depending upon whether you ask for an IMyDbContext
or a MyDbContext
.
To instruct the DI system to give you the same instance for both types, use the following approach:
services.AddDbContext<MyDbContext>();
services.AddScoped<IMyDbContext>(sp => sp.GetRequiredService<MyDbContext>());
The first call registers MyDbContext
and the second simply forwards requests for IMyDbContext
to that same scoped MyDbContext
instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With