我是Entity Framework和ASP.Net MVC的新手,他们大部分都是从教程中学到的,而且对这两者都没有深入的了解。 (我确实有.Net 2.0,ADO.Net和WebForms的经验)
我当前的疑问来自于我实体化实体对象的方式。
基本上我在我的控制器中这样做:
public class PostsController : Controller {
private NorthWindEntities db = new NorthWindEntities();
public ActionResult Index() {
// Use the db object here, never explicitly Close/Dispose it
}
}
我这样做是因为我在一些MSDN博客中发现它对我来说似乎具有权威性,我认为这是一种正确的方法。
但是,我觉得这很不容易。虽然它为我节省了很多代码,但我已经习惯了:
using (NorthWindEntities db = new NorthWindEntities() {
}
在每个需要连接的方法中,如果该方法调用其他需要它的方法,它会将db作为参数传递给它们。这就是我在Linq-to-SQL存在之前用连接对象做的所有事情。
让我感到不安的另一件事是NorthWindEntities实现了IDisposable,按照惯例,我应该调用它的Dispose()方法,而我不是。
您如何看待这个?
像我一样实例化实体对象是否正确?是否应该通过为每个查询打开和关闭它们来处理它的连接?
或者我应该使用using()子句显式处理它?</ p>
谢谢!
答案 0 :(得分:22)
Controller本身实现了IDisposable。因此,您可以覆盖Dispose并处理在实例化控制器时初始化的任何内容(如对象上下文)。
控制器只能存在一个请求。因此,在一个动作中使用并为整个控制器设置一个对象上下文的情境数量完全相同:1。
这两种方法之间的最大区别在于,在呈现视图之前,操作已经完成。因此,如果在操作内的using语句中创建ObjectContext,则ObjectContext将在呈现视图之前被释放。因此,您最好在操作完成之前从所需的上下文中读取任何内容。如果传递给视图的模型是一些类似于IQueryable的惰性列表,则在呈现视图之前会放置上下文,当视图尝试枚举IQueryable时会导致异常。
相比之下,如果在初始化Controller时初始化ObjectContext(或者编写延迟初始化代码,导致在运行操作时初始化它)并在Controller.Dispose中处理ObjectContext,那么上下文仍将是在渲染视图时。在这种情况下,将IQueryable传递给视图是安全的。控制器将在视图呈现后不久进行处理。
最后,如果我没有指出让控制器完全了解实体框架可能是一个坏主意,那将是我的疏忽。查看为模型和存储库模式使用单独的程序集,让控制器与模型通信。谷歌搜索会在这方面发生很多变化。
答案 1 :(得分:3)
你在这里提出了一个很好的观点。 ObjectContext应该存在多长时间?所有模式和实践书籍(如Dino Esposito的Microsoft-NET-Architecting-Applications)都告诉您DataContext不能长寿,也不应该缓存。
我只是想知道为什么在你的情况下没有一个ControllerBase类(我不知道MVC实现,所以请跟我一起),其中ObjectContext为所有控制器启动一次。特别要考虑已经由实体框架实现的Identity Map Pattern。即使您需要将另一个控制器作为PostsController调用,它仍然可以使用相同的Context并提高性能。