2010-07-29 111 views
2

我刚开始使用EF4与存储库模式。我不得不在每次使用上下文之后调用dispose方法,或者在使用块中将代码包装在周围。我可以在不写每一个方法的情况下使用ObjectContext,或者在存储库中处理这个问题有更好的方法。
另外我不想从UI中传递ObjectContext到存储库。实体框架4 ObjectContext生命周期

回答

2

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

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

} 

哪些希望是你正在使用的模式。只要使用“使用”语句,调用dispose似乎有点矫枉过正。

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

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

如果您对基于线程的单例感兴趣。首先了解Singleton模式,然后查看有关“DataContext”线程的blog。您将不得不将“DataContext”类型更改为ObjectContext类,但它会起作用。

编辑

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

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"); 
} 

什么也没有发生,这可能会让人困惑。