Jon*_*ood 22 c# asp.net-mvc entity-framework idisposable using
我对ASP.NET MVC应用程序中实体框架上下文的期望生命周期有一些疑问.是不是最好尽可能在最短的时间内保持上下文?
请考虑以下控制器操作:
public ActionResult Index()
{
IEnumerable<MyTable> model;
using (var context = new MyEntities())
{
model = context.MyTable;
}
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将不起作用,因为在视图呈现页面时,实体框架上下文已超出范围.其他人如何构建上面的代码?
Bri*_*per 51
让我们争议吧!
我不同意一般MVC + EF的共识,即在整个请求中保持上下文活动是一件好事,原因有很多:
性能低下 您知道创建新数据库上下文的成本是多少吗?好吧......" DataContext很轻,创建起来并不昂贵 "来自MSDN
让IoC出错并且它看起来很好......直到你上线 如果你设置了你的IoC容器来为你处理你的上下文并且你弄错了,你真的错了.我已经两次看到从IoC容器创建的大量内存泄漏并不总是正确地处理上下文.在正常的并发用户级别中,服务器开始崩溃之前,您不会意识到自己设置错误了.它不会在开发中发生,所以做一些负载测试!
意外延迟加载 您可以返回最新文章的IQueryable,以便您可以在主页上列出它们.有一天,要求其他人显示相应文章旁边的评论数量.所以他们在View中添加了一些简单的代码来显示注释计数......
@foreach(var article in Model.Articles) {
<div>
<b>@article.Title</b> <span>@article.Comments.Count() comments</span>
</div>
}
Run Code Online (Sandbox Code Playgroud)
看起来很好,工作正常.但实际上您没有在返回的数据中包含注释,因此现在这将为循环中的每篇文章进行新的数据库调用.选择N + 1问题.10篇文章= 11个数据库调用.好吧,所以代码是错误的,但这是一个容易犯的错误,所以它会发生.
您可以通过在数据层中关闭上下文来防止这种情况发生.但是,在article.Comments.Count()上,代码是否会因NullReferenceException而中断?是的,它会强制您编辑数据层以获取View层所需的数据.这应该是怎样的.
代码味道 从View中访问数据库有一些问题.你知道IQueryable实际上并没有真正命中数据库,所以忘了那个对象.确保数据库在离开数据层之前已被命中.
所以答案
你的代码应该(在我看来)像这样
数据层:
public List<Article> GetArticles()
{
List<Article> model;
using (var context = new MyEntities())
{
//for an example I've assumed your "MyTable" is a table of news articles
model = (from mt in context.Articles
select mt).ToList();
//data in a List<T> so the database has been hit now and data is final
}
return model;
}
Run Code Online (Sandbox Code Playgroud)
控制器:
public ActionResult Index()
{
var model = new HomeViewModel(); //class with the bits needed for you view
model.Articles = _dataservice.GetArticles(); //irrelevant how _dataService was intialised
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
一旦你完成了这个并理解了这一点,那么也许你可以开始尝试拥有一个IoC容器句柄上下文,但绝对不是之前.警告我 - 我看过两次大规模的失败:)
但老实说,做你喜欢的,编程很有趣,应该是一个偏好的问题.我只是告诉你我的.但无论你做什么,都不要开始在每个控制器或每个请求中使用IoC上下文,因为"所有很酷的孩子都在这样做".这样做是因为你真正关心它的好处并理解它是如何正确完成的.
我同意每个请求一个上下文,我们通常通过绑定上下文来实现这一点.使用Ninject的InRequestScope,它运行得很好,是:
Bind<MyContext>().ToSelf().InRequestScope();
Run Code Online (Sandbox Code Playgroud)
最好的做法是将集合枚举为尽可能接近查询,即:
public ActionResult Index()
{
IEnumerable<MyTable> model;
using (var context = new MyEntities())
{
model = (from mt in context.MyTable
select mt).ToArray();
}
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
这有助于您避免在视图中无意中增加查询.
| 归档时间: |
|
| 查看次数: |
16981 次 |
| 最近记录: |