Asp.net mvc 为什么我们需要避免在ASP.NET MVC视图中直接使用IQueryable?
有人告诉我,从ASP.NETMVC视图直接引用IQueryable是一种不好的做法,但我没有找到任何明确的解释。有些人在访问视图中的IQueryable或DbContext时可能遇到“disposed object”错误,但这不是我关心的问题 下面是我如何实现一个简单的控制器和一个包含用户列表的视图Asp.net mvc 为什么我们需要避免在ASP.NET MVC视图中直接使用IQueryable?,asp.net-mvc,entity-framework,ienumerable,iqueryable,Asp.net Mvc,Entity Framework,Ienumerable,Iqueryable,有人告诉我,从ASP.NETMVC视图直接引用IQueryable是一种不好的做法,但我没有找到任何明确的解释。有些人在访问视图中的IQueryable或DbContext时可能遇到“disposed object”错误,但这不是我关心的问题 下面是我如何实现一个简单的控制器和一个包含用户列表的视图 public ActionResult Index() { return View(db.Users); } 在我看来 @model IEnumerable<User> &
public ActionResult Index()
{
return View(db.Users);
}
在我看来
@model IEnumerable<User>
<ul>
@foreach (var user in Model)
{
<li>@user.UserName</li>
}
</ul>
我有点好奇为什么我要这么做。我可以说后一种方法比第一种方法更糟糕,因为数据集在我的应用程序中迭代了两次,第一次是通过ToList()
方法构造List
对象,第二次是通过视图中的foreach
循环来渲染
项
因此,这意味着后一种方法必须有一个更好的地方,我还没有发现。即使在ASP.NET论坛或Microsoft MSDN网站上,他们也提供了后一种方法的示例,但没有给出任何理由,或者我遗漏了什么
有人能给我解释一下这些简单的基本知识吗
非常感谢。如果您通过了
IQueryable
您正在创建一个视图,您可以在视图中移动业务逻辑,而不是严格地呈现业务模型。这是因为尚未对数据库执行IQueryable
,这给视图留下了许多选项,如过滤更多或检索附加属性等,这些都应该在控制器中完成(很好)
到你的第二点。如果返回的对象太多,以致在循环中对它们进行迭代(for
/foreach
/etc)导致性能下降的原因比你有更大的问题,比如如何用HTML发送/呈现你正在构建的巨大列表,再加上从数据库中实际检索这样的列表,这将是瓶颈
最后,您需要处理底层DbContext。当您的控制器被释放时,这可以注册到您的控制器进行清理,但我可以看到许多程序员忘记了这样做,从而留下了开放的数据库连接 您不应该使用IQueryable,因为您还没有具体化查询,所以每次具体化时都会调用数据库。如果您先处理数据库,然后尝试具体化,您将无法访问底层数据库db@BradleyUffner他不想在视图中使用IQueryable而不是视图模型,因为控制器是为每个请求创建的,所以如果我将DbContext的dispose逻辑添加到析构函数或dispose()中方法如果遵循IDisposable模式,则每当释放控制器时,都将释放DbContext。当您的控制器被释放并且您的视图被遗忘时(例如,当您的应用程序关闭时),保持IQueryable活动的意义是什么?我了解你关于分离关注点和泄漏抽象的想法。谢谢你的解释。如果我创建一个包装器枚举器和一个扩展方法,将IQueryable强制转换为我的包装器枚举器,这样传递给视图的实例实际上是一个IEnumerable,但在调用foreach或GetEnumerator()之前,查询仍然不会执行,怎么样?@Nguyenthanha-为什么要这样做?在内存中对集合进行迭代相当快。如果您的集合非常大,那么最慢的部分将是从数据库中检索,而不是在数据库上循环。如果集合非常大,并且数据库检索速度非常慢,那么您应该向控制器添加某种类型的分页或过滤逻辑。我认为对视图使用open
IQueyrable
对象(包装或不包装)没有任何好处,尤其是与性能无关。视图可以是包含数据列表的JsonResult
。它并不总是一个HTML视图。我关心的是,使用ToList()
意味着将所有数据放在应用程序内存中,这看起来像是一种“缓冲”方式;这意味着内存密集型。在使用IQueryable
时,您将遍历每个项目,一个接一个地加载到应用程序内存中,这看起来像是一种“流式”方式。对吗?好的,现在知道了。非常感谢您的关注和清晰的解释。:)我刚刚想到了一个案例,可以证明将IQueryable
传递给视图不是一个好做法。考虑到有不同的开发人员处理控制器和视图的情况。因此,当将IQueryable
传递给视图时,在controller上工作的开发人员将不知道开发人员将如何在视图实现中使用该实例。因此,为了安全和良好的实践,他们应该提供一个集合对象,以避免一个数据库查询可以多次运行,而不管视图开发人员如何做。
public ActionResult Index()
{
return View(db.Users.ToList());
}