为什么基架生成的控制器在将其 DbContext 的 DbSet 属性传递到视图之前将其转换为列表?



我遵循微软的ASP。. NET MVC教程,作为其中的一部分,我通过脚手架为模型Movie生成了CRUD操作。

Index视图的顶部有以下一行:

@model IEnumerable<MvcMovie.Models.Movie>

控制器通过首先将DbContextDbSet<MvcMovie.Models.Movie>转换为List来传递该对象:

public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}

教程确认这是预期的行为:

检查索引。cshtml视图和Movies控制器中的Index方法。注意代码在调用View方法时如何创建List对象。代码将这个Movies列表从Index操作方法传递给视图:

然而,看看DbSet类,它实现了IEnumerable<TEntity>,在本例中,TEntity是Movie对象。那么,为什么要把它转换成List呢?

我通过按原样传递_context.Movie进行了测试,它似乎工作得很好。

这样做有什么原因吗?

我通过传递_context来测试这一点。电影是这样的,它似乎工作得很好。

看起来工作得很好,在最简单的情况下,它甚至可以工作。然而:

View方法需要遍历传入的数据。在DbSet<T>的情况下,这意味着整个数据库表将被SELECT编辑为同步。。关于同步和异步操作(包括数据库调用)之间的区别,已经有很多帖子了,所以我不会深入讨论细节,只是说:在大多数情况下,必须避免同步使用实体框架核心。
这意味着,为了确保查询的异步执行,必须使用其中一个异步查询执行器,ToListAsync是一个常见的选择,尽管ToArrayAsync也可以很好地用于此目的。

这是第一部分。第二部分是,由于要返回对DbSet<T>的引用,因此数据尚未在内存中,因此在执行查询的某个时间点之前,需要打开到数据库的连接。另一个问题是,查询最终可能会被执行多次,这取决于将结果发送回客户机的实现。