深入理解延迟加载和处理MVC .net中的错误

sta*_*low 5 c# asp.net-mvc entity-framework lazy-loading

我试图写下以下问题的完整详细答案: 为什么"Dispose"工作,而不是"使用(var db = new DataContext())"?

所以我设置了我的项目,包括:

部门和员工使用实体框架

所以我的行动方法是这样的:

public ActionResult Index()
    {

        IEnumerable<department> d;
        using (var ctx = new ApplicationDbContext())
        {

            d = ctx.departments;

        }


        return View(d);
}
Run Code Online (Sandbox Code Playgroud)

很自然地会发现这会导致常见的错误:

The operation cannot be completed because the DbContext has been disposed
Run Code Online (Sandbox Code Playgroud)

当我想解决它时,我做了以下[强制加载而不是轻松加载]:

 public ActionResult Index()
    {

        IEnumerable<department> d;
        using (var ctx = new ApplicationDbContext())
        {

            d = ctx.departments.toList();

        }


        return View(d);
}
Run Code Online (Sandbox Code Playgroud)

所以我试图了解引擎盖下的内容并查看View()方法的返回类型.我达到了以下' 正确 '的假设:

1-在using语句中以延迟加载方式调用模型[d].

2-因此当模型[d]被发送到视图以生成页面时,DbContext已经被using语句的最后一个大括号括起来了.

3-我们通过以急切的加载方式将模型[d]发送到视图来解决这种情况.

然后我继续我的假设被证明是" 错误的 "如下:

4-因为View()方法返回的是ViewResult对象,它也是一个ActionResult ..然后我可以在using语句中生成这个对象,然后将它返回给用户.

所以我做了以下事情:

public ActionResult Index()
    {

        ActionResult myView;

        using (var ctx = new ApplicationDbContext())
        {

            IEnumerable<department> d = ctx.departments;

            myView =  View(d);

        }


        return myView;
    }
Run Code Online (Sandbox Code Playgroud)

所以我现在告诉自己,当我运行它时,ViewResult对象[myView]将被创建并将返回给用户并且将遇到No Error.

但是我很惊讶发生了同样的错误:

The operation cannot be completed because the DbContext has been disposed
Run Code Online (Sandbox Code Playgroud)

我很惊讶这个懒惰的加载是如何真正的懒惰,只在最后一刻加载.

所以我继续我的' 错误 '假设如下:

5-可能是我需要强制View()方法在using语句中执行结果.所以我使用了这个方法ExecuteResult(ControllerContext).

现在我以为我可以运行动作方法没有任何错误,但同样的错误发生了:

The operation cannot be completed because the DbContext has been disposed.
Run Code Online (Sandbox Code Playgroud)

所以现在我的问题是:

在MVC框架中进行延迟加载查询的执行!

或者让我重新解释我的问题如下:

为什么View(d)方法在[d]对象超出使用状态时迭代,而不是在视图(d)方法在using语句内时.

我只需要理解为什么我的假设是错误的.. Thanx在先进

sta*_*low 4

好的。我找到了一个非常有说服力的答案,如下:

我开始阅读有关 MVC5 生命周期的内容,并在网上找到了很多文章。其中之一是以下链接:http://www.dotnet-tricks.com/Tutorial/mvc/TbR0041112-Asp.net-MVC-Request-Life-Cycle.html 所以我复制了图片并添加了我的评论如下 [礼貌:www.dotnet-tricks.com]

在此输入图像描述

然后我在另一篇文章[此处:http: //www.codemag.com/Article/1312081]中读到,如何将视图渲染为字符串并将其作为操作方法的返回类型返回。这样我就可以在 using 语句内使用延迟加载并渲染视图。

所以我所做的就是对我的操作方法进行以下更改[解释作为评论包含在内]

 // GET: /dept/
    public string  Index()
    {

        IView myView;
        string result;
        using (var ctx = new ApplicationDbContext())
        {
            //my model brought using the dbContext
            IEnumerable<department> d = ctx.departments;

            // now because I want to render the View here [forcibly] and not waiting
            //for the normal MVC pipeline to render my View I had to jump to the ViewEngine
            //and ask it to render my View [while i am still inside this using statement]
            // so referring to the excellent article on :http://www.codemag.com/Article/1312081
            //I did the following:
            ControllerContext.Controller.ViewData.Model = d;
            ViewEngineResult viewEngResult = ViewEngines.Engines.FindView(ControllerContext, "~/Views/dept/Index.cshtml", null);

            myView = viewEngResult.View;
            //till this point the View is not rendered yet
            StringWriter tw = new StringWriter();// used to render the View into string
            ViewContext vc = new ViewContext(ControllerContext, myView, ControllerContext.Controller.ViewData, ControllerContext.Controller.TempData, tw);
            //it is the following method .Render(viewContext, textWriter) that will start iterating on the IEnumerable<department> object
            myView.Render(vc, tw);

            result = tw.ToString();// the rendered View is now written as string to the result
            tw.Dispose();
        }

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我很高兴看到我的页面成功呈现,没有出现那个著名的处理错误;查看结果:

在此输入图像描述


总结一下:

我的问题的答案是:

当您从操作方法返回 ViewResult 或 ActionResult 时;视图仍未呈现。一旦它到达 ViewEngine 的管道,并且 ViewEngine 触发方法 .Render(),此时延迟加载对象将需要 dbContext,并会导致著名的 dbContext 处置错误。我还展示了如何在操作方法本身内渲染视图。甚至在 dbContext 的 using 语句中;我可以避免这个处理错误。

谢谢大家:)