为什么我们需要避免在 ASP.NET MVC 视图中直接使用 IQueryable?

Why do we need to avoid using IQueryable directly in an ASP.NET MVC view?

有人告诉我,从 ASP.NET MVC 视图直接引用 IQueryable 是一种不好的做法,但我还没有找到任何明确的解释。有些人可能在访问视图中的 IQueryable 或 DbContext 时遇到 "disposed object" 错误,但这不是我关心的问题。

下面是我如何实现一个简单的控制器和一个包含用户列表的视图

public ActionResult Index() 
{
    return View(db.Users);
}

在我看来

@model IEnumerable<User>

<ul>
@foreach (var user in Model)
{
    <li>@user.UserName</li>    
}
</ul>

我被告知我应该 return "collection object" 而不是将 IQueryable 传递给视图。

public ActionResult Index() 
{
    return View(db.Users.ToList());
}

我有点好奇为什么我必须这样做。我可以说后一种方法比我的第一种方法更糟糕,因为数据集在我的应用程序中迭代了两次,第一次是通过 ToList() 方法构造 List 对象,第二次是 foreach在我的视图中循环以呈现 <li> 项。

所以这意味着后一种方法一定有更好的地方我还没有发现。即使在 ASP.NET 论坛或 Microsoft MSDN 站点中,他们也提供了后一种方法的示例,但没有给出任何理由,还是我遗漏了什么?

任何人都可以为我解释一下这个简单的基本内容吗?

非常感谢。

如果您通过 IQueryable,您将创建一个 leaky abstraction where you can essentially move business logic in the view instead of strictly rendering the business model. This is because IQueryable has not yet been executed against the database which leaves a lot of options to the view like filtering more or retrieval of additional properties etc which should really be done in the Controller (good Separation of Concerns)。

关于你的第二点。如果您要返回如此多的对象,以至于在循环中迭代它们(for/foreach/等)会导致性能下降,而不是您遇到更大的问题,例如如何处理 sending/rendering您正在构建的 HTML 中的巨大列表与从数据库中实际检索此类列表相结合将成为瓶颈。

最后您需要处理底层 DbContext。这可以在您的控制器被处理时注册到您的控制器以进行清理,但我可以看到许多程序员忘记这样做从而留下打开的数据库连接。