c# - 关于Entity Framework Context Lifetime的问题

标签 c# asp.net-mvc entity-framework using idisposable

我对 ASP.NET MVC 应用程序中 Entity Framework 上下文的预期生命周期有一些疑问。在尽可能短的时间内保持上下文事件不是最好的吗?

考虑以下 Controller 操作:

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

    using (var context = new MyEntities())
    {
        model = context.MyTable;
    }

    return View(model);
}

上面的代码将不起作用,因为 Entity Framework 上下文在 View 呈现页面时超出了范围。其他人会如何构造上面的代码?

最佳答案

让我们开始争论吧!

我不同意一般的 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>
}

看起来不错,工作正常。但实际上您没有在返回的数据中包含评论,所以现在这将为循环中的每篇文章进行新的数据库调用。选择 N+1 个问题。 10 篇文章 = 11 次数据库调用。好吧,代码是错误的,但这是一个很容易犯的错误,所以它会发生。

您可以通过关闭数据层中的上下文来防止这种情况发生。但是代码不会因 article.Comments.Count() 上的 NullReferenceException 而中断吗?是的,它会强制您编辑 Data 层以获取 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;
}

Controller :

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 容器处理上下文,但绝对不是之前。请注意我的警告 - 我见过两次大规模失败:)

但老老实实做自己喜欢的事,编程很有趣,应该是一个偏好的问题。我只是告诉你我的。但是无论您做什么,都不要仅仅因为“所有酷 child 都在这样做”就开始为每个 Controller 或每个请求使用 IoC 上下文。这样做是因为您真正关心它的好处并了解如何正确完成。

关于c# - 关于Entity Framework Context Lifetime的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10777630/

相关文章:

asp.net-mvc - 将ASP.NET MVC View 上的各个按钮映射到 Controller 操作

c# - EntityFramework - 是否可以将整个上下文数据库加载到内存中?

.net - Entity Framework - 反射(reflect)外键和关系/关联

c# - 将值从 Dispatcher.RunAsync() 返回到后台线程

c# - 具有不同类型的单排序C#列表?

css - 动态 css 类取决于实体属性的值

asp.net-mvc - html 属性中的 Razor 语法

c# - 表拆分 EF Core

c# - (-) Convert 方法中使用的符号

c# - 将两个 xml 文件合并为一个文件的最快方法是什么