您是否有一个或两个上下文定义并不是真正的问题,而是 DbContext 的任何实例的作用域以及是否可以在两个代码块之间共享单个引用。
例如,如果我在 MVC 项目中有一些代码正在执行以下操作:
using (var context = new AppContext())
{
var myEntity = context.Entities.Single(x => x.EntityId = entityId);
SomeService.DoSomething(myEntity);
}
和一个服务库做类似的事情:
public void DoSomething(AppEntity someEntity)
{
using(var context = new AppContext())
{
someEntity.Status = "DidSomething";
context.Attach(someEntity);
context.Entity(someEntity).State = EntityState.Modified;
context.SaveChanges();
}
}
或类似的情况,那么您可能正在为追踪陈旧状态相关问题而感到不安。两个代码块可以引用相同的 DbContext type 但不同的 DbContext instances 这意味着控制器的 DbContext 引用可能不会反映或跟踪其他库上下文的实体已经承诺了。
作为一般规则,实体不应离开生成它的 DbContext 实例的范围。任何这样做的实体都应该被认为是分离的,但如果它没有显式地与 DbContext 实例分离,这可能会导致错误,具体取决于产生它的 DbContext 的寿命。如果一个程序集引用了第二个程序集,那么您可以使用依赖注入和 IoC 容器跨调用管理单个 DbContext 实例的生命周期范围,或者您可以使用工作单元提供程序来提供 DbContext 并管理该 DbContext 的生命周期.这样,当 MVC 引用您的库时,它会在调用时共享一个 DbContext 实例,但如果通过另一种方式调用,它会为从该场景接收的实体解析一个合适的 DbContext 实例。
对于较大的系统,谨慎的做法是使用单独的 DbContext 定义和简化的实体定义。在查询/跟踪实体时,更小、更简单、寿命短的 DbContext 运行效率更高。对于可能被频繁调用以针对数据进行操作的服务,使用一个针对较小 DbContext 的简化实体会好得多。获取实体、检查、修改和提交,而不是尝试在完整大小的 DbContext 实例上使用完整大小的实体来附加、修改和提交。像这样的模型将使用最小有效载荷 (DTO) 而不是实体作为有效载荷。调用者会收到一个指示,表明他们的作用域实体是否应该被刷新。