本文介绍了关于实体框架上下文生存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实体框架范围内的ASP.NET MVC应用程序所需的生命周期的一些问题。是不是最好保持上下文活着最短的时间内?

I have some questions about the desired lifetime of an Entity Framework context in an ASP.NET MVC application. Isn't it best to keep the context alive for the shortest time possible?

考虑下面的控制器动作:

Consider the following controller action:

public ActionResult Index()
{
    IEnumerable<MyTable> model;

    using (var context = new MyEntities())
    {
        model = from mt in context.MyTable
                select mt;
    }
    return View(model);
}

上面的code将无法工作,因为实体框架上下文超出范围,而视图呈现页面。如何将其他结构上的code?

The code above won't work because the Entity Framework context has gone out of scope while the view renders the page. How would others structure the code above?

推荐答案

让我们有争议的!

我不同意用一般MVC + EF共识,保持上下文,活在整个请求是有许多原因的好事:

I disagree with the general MVC + EF consensus that keeping a context alive throughout the entire request is a good thing for a number of reasons:

低性能提升
你知道一个新的数据库环境有多贵创建是什么?嗯......的一个DataContext是轻量级的,不昂贵创建的从MSDN

获取IoC的错误,直到你去它会看起来很好..直播
如果你设置你的IoC容器处置你对你的背景,你弄错了,你真的真的搞错了。我已经的两次的从IoC容器并不总是正确处理上下文的创建,现在看到大量的内存泄漏。你不会意识到你已经将它设置错了,直到你的服务器启动过程中并发用户的正常水平摇摇欲坠。它不会在发展中发生,所以做一些负载测试!

Get the IoC wrong and it'll seem fine.. until you go liveIf you set up your IoC container to dispose of your context for you and you get it wrong, you really really get it wrong. I've twice now seen massive memory leaks created from an IoC container not always disposing of a context correctly. You won't realise you've set it up wrong until your servers start crumbling during normal levels of concurrent users. It won't happen in development so do some load tests!

意外延迟加载
你返回你最近的文章一个IQueryable,让您可以在您的主页列出。有一天,有人问是显示评论数相应的文章旁边。因此,他们增加code 简单位到视图显示,像这样的评论了......

Accidental lazy loadingYou return an IQueryable of your most recent articles so that you can list them on your homepage. One day someone else is asked to show the number of comments next to the respective article. So they add a simple bit of code to the View to show the comment count like so...

@foreach(var article in Model.Articles) {
    <div>
        <b>@article.Title</b> <span>@article.Comments.Count() comments</span>
    </div>
}

外观精致,做工精细。但实际上你并没有包括在返回的数据的注释所以现在这将创建一个新的数据库调用在循环中的每一篇文章。选择N + 1的问题。 10条= 11的数据库调用。好了,所以在code是错误的,但它是一个容易犯的错误,因此不会发生。

Looks fine, works fine. But actually you didn't include the comments in your returned data so now this will make a new database call for each article in the loop. SELECT N+1 issue. 10 article = 11 database calls. Okay so the code is wrong but it is an easy mistake to make so it will happen.

您可以通过关闭上下文倒在你的数据层prevent这一点。但不会对article.Comments.Count一个NullReferenceException的code中断()?是的,它会因此它会迫使你编辑的数据层来获得所需视图层的数据。这怎么是应该的。

You can prevent this by shutting your context down in you data layer. But won't the code break with a NullReferenceException on the article.Comments.Count() ? Yes it will so it will force you to edit the Data layer to get the data needed for the View layer. This is how is should be.

code气味
只是有一些错误有关从视图访问数据库。你知道一个IQueryable实际上并没有触及数据库尚未权利,使忘记对象。请确保它使你的数据层之前,你的数据库被击中。

Code smellThere is just something wrong about hitting the database from your View. You know that an IQueryable hasn't actually hit the database yet right so forget that object. Make sure your database is hit before it leaves your data layer.

所以答案

您code应该(在我看来)像这样

Your code should be (in my opinion) like this

数据层:

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

控制器:

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

一旦你做到了这一点,并明白这一点,那么也许你就可以开始与具有IoC容器处理方面的实验,但绝对不是之前。的团长我的警告 - 我看到了两个大型的故障:)

Once you have done this and understand this then perhaps you can begin experimenting with having an IoC container handle context but definitely not before. Head my warning - I've seen two large scale failures :)

不过,老老实实做你喜欢什么,编程很有趣,应该是preference的问题。我只是告诉你我的。但是,不管你做什么,不要开始使用每个控制器或每个请求IoC上下文中,只是因为所有时尚的年轻人都这样做。这样做,因为你真的真正关心它的好处,并了解它是如何做正确。

But honestly do what you like, programming is fun and should be a matter of preference. I'm just telling you mine. But whatever you do, don't start using IoC context per controller or per request just because "all the cool kids are doing it." Do it because you really truly care about it's benefits and understand how it's done correctly.

这篇关于关于实体框架上下文生存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 22:43