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在先进
好的。我找到了一个非常有说服力的答案,如下:
我开始阅读有关 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 语句中;我可以避免这个处理错误。
谢谢大家:)