使用 DbContext 接口注册 AspNetCore 2.1 身份系统 [英] Register AspNetCore 2.1 Identity system with DbContext interface
问题描述
我正在开发一个 AspNetCore 2.1 WebApi.我正在使用 Microsoft.Extensions.DependencyInjection
、AspNetCore.Identity
和 EntityFrameworkCore
.
I am working on an AspNetCore 2.1 WebApi. I am using Microsoft.Extensions.DependencyInjection
, AspNetCore.Identity
, and EntityFrameworkCore
.
在我的 DI 注册中,我调用:
In my DI registrations, I am calling:
services.AddDbContext<IMyDbContext, MyDbContext>();
很好,对吧?传递合同.但是后来我遇到了一个异常,即 Identity Manager 类(UserManager
、RoleManager
等)无法在依赖注入容器中重新解析,因为它们使用的身份存储(UserStore
、RoleStore
等)无法解析它们的 DI 参数(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>();
... 这很糟糕,因为身份存储正在寻找具体的上下文并且它没有在 DI 中注册.该扩展需要一个 class
,它可以解析为 DbContext
- 我不能向接口 IMyDbContext
添加隐式运算符来给它一个DI 扩展方法可以使用的隐式转换.
... 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.
所有这些都让我执行了一个相当丑陋的 DI 注册:
All this has me performing a rather ugly DI registration:
services
.AddDbContext<IMyDbContext, MyDbContext>()
.AddDbContext<MyDbContext>();
- DI 注册可能会导致我尚未遇到的其他下游问题(线程安全、事务性).
我的猜测是我可以通过滚动我自己的 IServiceCollection
扩展和/或自定义身份存储来清理 DI 注册 - 这在这里看起来真的有点矫枉过正,否则我不需要超越默认内置身份存储.
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.
我也不想删除 <interface,concrete>
上下文注册,因为它会渗透到我所有的构造函数注入中,而且看起来错误.
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.
有没有人已经解决了这个问题并找到了解决方法?或者至少有人可以确认/否认 DI 中的双重(接口和具体)上下文注册不会导致其他问题?
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?
提前致谢!
推荐答案
默认情况下,当你调用 AddDbContext
时,你注册了一个 scoped DbContext
> 实例.这意味着在处理单个请求的任何地方,通过 DI 请求所述 DbContext
都会为您提供相同的实例.通过您的双重注册,DI 系统将为您提供不同的实例,具体取决于您请求的是 IMyDbContext
还是 MyDbContext
.
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
.
要指示 DI 系统为两种类型提供相同的实例,请使用以下方法:
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>());
第一个调用注册 MyDbContext
,第二个调用只是将 IMyDbContext
的请求转发到同一个作用域 MyDbContext
实例.
The first call registers MyDbContext
and the second simply forwards requests for IMyDbContext
to that same scoped MyDbContext
instance.
这篇关于使用 DbContext 接口注册 AspNetCore 2.1 身份系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!