实体框架4 ObjectContext Lifetime

时间:2010-07-29 12:11:41

标签: entity-framework

我刚开始使用EF4和存储库模式。我必须在每次使用上下文之后调用dispose方法或在using块中包装代码。我可以在我编写的每个方法中使用ObjectContext而不执行此操作,或者在存储库中有更好的方法来处理它 另外,我也不想将UIContext从UI传递到存储库。

2 个答案:

答案 0 :(得分:5)

为了在没有依赖注入的情况下尽可能有效地执行此操作,我建议您为对象上下文实现一个私有的,延迟加载属性。

private ObjectContext _context;
private ObjectContext Context 
{ get 
    { 
        return _context ?? (_context = new ObjectContext()); 
    }
}

接下来,使您的存储库实现IDisposable并处理dispose方法中的对象上下文:

public Repository : IDisposable
{
     ...
     public void Dispose()
     {
         _context.Dispose();
     }
}

然后,您只需在所有方法中使用该属性,并在using语句中包装存储库的用法。

要减少数据库的流量,您还可以将保存分解为存储库中的单独方法,该方法只是将调用转发给对象上下文。这样,即使您不控制如何,您也可以在数据保存在UI层中时更好地控制。这意味着你可以做到

using (var repo = new Repository())
{
    repo.AddSomeStuff("this", "is", true);
    repo.ChangeSomethingElse("yes, please");
    repo.Save();
}

并且只有一次从EF到数据库的调用。另一方面,如果你这样做

using (var repo = new Repository())
{
    repo.AddSomeStuff("this", "is", true);
    repo.ChangeSomethingElse("yes, please");
}
没有任何事情发生,这可能令人困惑。

答案 1 :(得分:2)

使用对象上下文的一般模式是:

public BusinessObject GetSomething(){
   using (MyObjectContext context = new MyObjectContext()){
      //..do fun stuff
   }

}

希望你正在使用的模式。当你可以使用“使用”声明时,调用dispose似乎有点矫枉过正。

另一个选择是,如果您要在流中执行多个数据库查询。我已经看到了一种模式,你可以在线程中重用相同的上下文。人们基本上实现了基于线程的单例模式并传递了上下文。这样做的好处是不必重建上下文,也不必重新构建内存缓存。缺点是您可能遇到并发问题。有人更新了你在EF内部缓存的内容。

我猜第二种情况并不适用,因为它听起来像是在写一个小应用程序。 (该声明基于您对从UI传递上下文的评论......一个会吓到任何优秀代码架构师的声明。)

如果您对基于线程的单例感兴趣。首先了解Singleton模式,然后查看关于“DataContext”线程的blog。您必须将“DataContext”类型更改为ObjectContext类,但它可以工作。

修改

我会说我忽略了一个明显的解决方案,这将是下面的内容;​​)。只需使用基于属性的对象上下文并在using语句中播放存储库。它与上面的使用示例相同,但您可以实现IDisoposable。