Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
454 views
in Technique[技术] by (71.8m points)

c# - Register AspNetCore 2.1 Identity system with DbContext interface

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>();
  • a DI registration that may cause other issues (thread safety, transactional) downstream that I haven't encountered yet.

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...