Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 深入理解MVC.net中的延迟加载和处理错误_C#_Asp.net Mvc_Entity Framework_Lazy Loading - Fatal编程技术网

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

C# 深入理解MVC.net中的延迟加载和处理错误,c#,asp.net-mvc,entity-framework,lazy-loading,C#,Asp.net Mvc,Entity Framework,Lazy Loading,我试图对以下问题写一个完整详细的答案: 因此,我设立了我的项目,包括: 使用实体框架的部门和员工 所以我的行动方法是: public ActionResult Index() { IEnumerable<department> d; using (var ctx = new ApplicationDbContext()) { d = ctx.departments; }

我试图对以下问题写一个完整详细的答案:

因此,我设立了我的项目,包括:

使用实体框架的部门和员工

所以我的行动方法是:

public ActionResult Index()
    {

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

            d = ctx.departments;

        }


        return View(d);
}
当我想解决这个问题时,我做了以下几件事[强制迫不及待地加载,而不是简单地加载]:

 public ActionResult Index()
    {

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

            d = ctx.departments.toList();

        }


        return View(d);
}
我很惊讶这种惰性加载是多么的懒惰,而且只在最后一刻加载

因此,我继续我的错误假设如下:

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

现在我想我可以毫无错误地运行action方法了 但同样的错误再次出现:

The operation cannot be completed because the DbContext has been disposed.
所以我现在的问题是:

在MVC框架中执行延迟加载查询的位置

或者让我将我的问题重新表述如下:

为什么
View(d)
方法在[d]对象不在using语句中时迭代它,而不是在View(d)方法在using语句中时迭代它。

我只需要理解为什么我的假设是错误的。。 高级

IEnumerable
中的Thanx是一个允许延迟执行的接口。事实上,延迟执行是LINQ高效的根本原因。现在,您的假设都是正确的,但是您缺少一个关键概念:在.NET中以延迟执行的形式延迟加载实现

了解强制枚举如何立即计算延迟代码。第一个示例工作的原因是调用了
ToList()
,强制枚举并执行代码。在第二种情况下,对视图对象的分配保持延迟,因为没有通过将结果分配给
view

但是,您可以在using块内执行此操作,以强制代码在执行dispose之前执行:

IEnumerable<department> d = ctx.departments;

// ToList() here forces the evaluation of the deferred code
myView =  View(d.ToList());
IEnumerable d=ctx.departments;
//这里的ToList()强制计算延迟代码
myView=View(d.ToList());

回答您关于MVC管道的问题:MVC管道不会计算您放置在
ViewResult
中的对象,只是为了使视图本身能够使用它而对其进行适当的强制转换。因此,它从不执行枚举并强制执行代码。在您的视图中,这是您的呼叫。。。在这种情况下,类似于
foreach
ing您的
Model
。因此,当您的视图执行时,您的
using
语句早已被释放,因此延迟调用将失败。

许多LINQ方法将对序列进行流式处理,有些方法要求对整个序列进行缓冲和操作,但如果您对序列不做任何操作,它将不存在于内存中。

确定。我发现一个非常令人信服的答案如下:

我开始阅读有关MVC5生命周期的文章,并在网上找到了许多文章。其中之一是以下链接: 因此,我复制了这张照片并添加了我的评论如下[礼貌:www.dotnet-tricks.com]

然后,我在另一篇文章[here:]中阅读了如何将视图呈现为string,并将其作为action方法的返回类型返回。这样,我就可以在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;
    }
}
//获取:/dept/
公共字符串索引()
{
我的观点;
字符串结果;
使用(var ctx=new ApplicationDbContext())
{
//我的模型使用dbContext
IEnumerable d=ctx.departments;
//现在,因为我想在这里(强制)渲染视图,而不是等待
//为了让普通MVC管道渲染我的视图,我必须跳转到ViewEngine
//并要求它呈现我的观点[当我还在使用此语句时]
//因此,请参考关于以下内容的优秀文章:http://www.codemag.com/Article/1312081
//我做了以下工作:
ControllerContext.Controller.ViewData.Model=d;
ViewEngineResult viewEngResult=ViewEngines.Engines.FindView(ControllerContext,“~/Views/dept/Index.cshtml”,null);
myView=viewEngResult.View;
//到目前为止,还没有渲染视图
StringWriter tw=new StringWriter();//用于将视图渲染为字符串
ViewContext vc=新的ViewContext(ControllerContext,myView,ControllerContext.Controller.ViewData,ControllerContext.Controller.TempData,tw);
//以下方法.Render(viewContext,textWriter)将开始迭代IEnumerable对象
myView.Render(vc,tw);
result=tw.ToString();//渲染视图现在作为字符串写入结果
tw.Dispose();
}
返回结果;
}
}
我很高兴看到我的页面成功呈现,没有出现著名的处理错误;看到结果:


总之:

我的问题的答案是:

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


谢谢大家:)

这并没有回答MVC框架何时将
IEnumerable
计算为其值的问题;相反,它只会重复
The operation cannot be completed because the DbContext has been disposed.
IEnumerable<department> d = ctx.departments;

// ToList() here forces the evaluation of the deferred code
myView =  View(d.ToList());
 // 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;
    }
}