为什么在使用Entity Framework时需要重新初始化DbContext?

37

我不知道是否有更好的方法来使用 DbContext,因为在使用 WCF 时不建议将其设置为静态。因此,每次访问数据库时我们都需要创建它。

了解使用 Entity Framework 的所有优点后,有些优点变得无用了,因为我们每次都重新创建了 DbContext;而且更多的可能会导致开销,因为要考虑创建大型实体模型的过程。

你有什么看法?


有没有人愿意对将单个实例DataContext作为ref参数传递给需要处理该事务的所有不同方法的想法发表评论?这样,不同的对象可以向其中添加/删除实体,并且最终,在所有修改完成后,Context对象可以更新自身。 - Graham
2
@Graham:DataContext 仍然跟踪对检索到的“实体”所做的更改,并维护标识缓存,以确保多次检索到的实体使用相同的对象实例表示。它还是轻量级的,创建成本不高。请参阅 http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx。 - Rob
@Graham:这意味着在应用程序生命周期中持久化单个实例的 DataContext 可能是一个不好的主意。从我回答中的文章中可以看出:“如果您有一种自然的有限生命周期方式来管理 ObjectContext,例如短暂的表单、UnitOfWork 或 Repository,则相应地调整 ObjectContext 的范围可能是最好的选择。” - Rob
您可以在此处找到创建DbContext的成本:https://dev59.com/kXI-5IYBdhLWcg3wy7wd#37408810 - Matas Vaitkevicius
2个回答

57

管理生命周期

您是正确的,通常不建议使用单个静态实例的 DbContext

您使用 ObjectContext 的次数越多,它就会变得越大。 这是因为它持有对其曾经知道的所有实体的引用,基本上是您查询、添加或附加的任何内容。 因此,应重新考虑无限期共享同一 ObjectContext。

这些注释直接适用于 DbContext,因为它包装了 ObjectContext 以公开更简化和直观的 API。[参见文档]


建造成本

创建上下文的开销相对较低:

实际上,这个成本其实非常低,因为它主要涉及从全局缓存中通过引用复制元数据到新的ObjectContext。一般来说,我认为这个成本不值得担心...

处理短暂上下文的常见方法是将其包装在using块中:

using(DbContext context = new SomeDbContext())
{
    // Do work with context
}

为了方便测试,您可能希望让DbContext实现一些IDbContext接口,并创建一个工厂类ContextFactory<T> where T : IDbContext来实例化上下文。

这使您可以轻松地将任何IDbContext替换到您的代码中(例如,对象模拟的内存上下文)。


资源


感谢提供额外信息。 那么,在这种情况下,我们应该使用EF吗?例如ADO.net可以处理基本的数据库功能。 还是因为我们可以从EF中获得开发速度? - Boomer
1
从技术上讲,EF是ADO.NET的一部分,尽管它是ORM的一个附加抽象层。我个人喜欢使用EF,因为它有强类型和LINQ。我认为经典的DataSets要灵活性少得多。另请参见:http://stackoverflow.com/questions/5268546/ado-net-or-entity-framework-in-visual-studio-2008 - Rob
为了方便测试,您可能希望让您的DbContext实现一些IDbContext接口 - 我也倾向于这个方向。感谢确认。 - Jacobs Data Solutions
对于使用AddDbContext和DI的人来说,您可以从host.Services.CreateScope()方法中获益。DbContext默认为Scoped,因此如果您使用的不是WebApp(例如WebJob),只需创建一个新范围并从那里获取DB上下文即可。每次创建新范围时,您都会获得一个新的上下文。 - carraua

1
最佳的Web开发实践似乎是“每个Web请求一个上下文”,请参见适当的会话/DbContext生命周期管理。在使用WCF时,这个实践可以被转化为每个操作一个上下文(即每个WCF方法调用一个上下文)。
有不同的方法来实现这一点,但其中一种解决方案可能不被推荐,那就是创建一个新的上下文实例,并将其传递给业务类的构造函数:
public void WCFMethod()
{
  using (DBContext db = new DBContext())
  {
    BusinessLogic logic = new BusinessLogic(db);
    logic.DoWork();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接