我们说我已经扩展了身份框架dbContext
以构建我自己的身份框架,并且我已经注册了dbContext
并且获取实体的经过身份验证的控制器与当前ApplicationUser
相关的实体框架将导致由于循环引用而导致服务器错误的两个实体相关联。
我们不想序列化循环引用。
因此,我们在方法中创建了一个新的dbContext
,其中新的dbcontext
并且查询不相关的实体,这将起作用。但这是不可测试的,我们不希望我们的控制器严格依赖dbContext
,我们希望它被注入。
所以我们在构造函数中添加了第二个参数,不幸的是,这将使系统注入相同的dbContext
两次,而不是那么有用。
我们尝试创建一个继承自fakeDbContext
的类dbContext
并添加服务并使用它,但现在我们有两个dbcontext ,他们可能会生成迁移和配置和错误...
在新MVC6中执行此操作的正确方法是什么?
我发现如果我的控制器需要IEnumerable<dbContext>
我将所有对象注册为该类型的服务,那么只需将 startup.cs 中的部分加倍,我们在其中添加{ {1}}在服务注册区域我得到两个......
这里的缺点是我不知道哪一个是 virgin ,它看起来像是按照注册的顺序,但我不知道,如果这会改变。
我创建了一个dbContext
类,只有一个工厂方法使用TransientDbService
,它使用它来获取构造IserviceProvider
的选项,然后将其公开。我已将其注册为瞬态,然后在控制器中我需要此服务类型。
这里的缺点是,如果我需要第三个dbContext
我应该写更多的代码,更多的代码意味着错误并保护它。
根本没有两个dbContext。以下设置允许我没有关系的价值。
dbContext
这里的缺点是我不能使用我的模型图,使一切更复杂......
答案 0 :(得分:0)
在某些情况下,您认为没有跟踪查询会有所帮助是正确的,但有时您需要创建多个DbContext实例。
您通常在启动时使用AddDbContext<TContext>()
方法,以确保按请求创建上下文类型的实例,并在其上设置正确的DbContextOptions
和服务提供商。当您需要偏离此模式时,您可以选择一些选项,例如:
在派生的DbContext类中包含一个构造函数,该构造函数接受IServiceProvider
并将其传递给基础构造函数。确保您的控制器需要IServiceProvider
。完成此操作后,您应该能够使用以下内容手动创建DbContext
:
using(var context1 = new MyDbContext(serviceProvider),
var context2 = new MyDbContext(serviceProvider))
{ ...
为了避免必须更改派生DbContext
类型的构造函数签名,您可以利用DbContextActivator
类(它是我们的内部命名空间),例如:
using(var context1 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider),
var context2 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider)
{...
注意:如果您在启动时仍在使用AddDbContext<MyDbContext>(options => ...)
,则应自动从服务提供商处提取这些选项。但您也可以选择在构造函数中包含DbContextOptions
作为参数,或者为此覆盖OnConfiguring()
方法。
我给你的例子在一个使用区块中创建两个单独的DbContexts
,但你也应该能够将它们与常规&#34; per-request&#34;您将在控制器的构造函数中注入DbContext。
除了目前可用的这些选项之外,我还创建了一个新问题,以跟踪有关如何在同一请求中创建相同DbContext
类型的多个实例的其他可能改进: