假设我执行了一个查询并投射到一个匿名类型中;这将在服务器上执行评估:
var people = await context
.People
.OrderBy(x => x.Name)
.Select(x => new { x.Id, x.Surname, x.Forename })
.ToListAsync();
字符串
但是假设我执行一个查询,并且需要投影到一个具体类型中。
选项1:将结果Map到具体类型:
var people = (await context
.People
.OrderBy(x => x.Name)
.Select(x => new { x.Id, x.Surname, x.Forename })
.ToListAsync())
.Select(x => new PersonDto(x.Id, x.Surname, x.Forename));
型
选项2:在 “顶层投影” 中使用具体类型:
var people = await context
.People
.OrderBy(x => x.Name)
.Select(x => new PersonDto(x.Id, x.Surname, x.Forename));
.ToListAsync()
型
关于(2),文档中指出,在顶级投影中,一些评估在数据库中执行,一些在客户端执行。(但文档显示了一个匿名类型的客户端函数的示例,因此它与我的用例不同。)
在这个具体的例子中,我假设所有的计算都是在服务器上执行的,并且(2)只是(1)的捷径,即它们在功能上是等价的,这对吗?
1条答案
按热度按时间u5rb5r591#
提问:
回答
显然,
PersonDto
对象是在客户端示例化的,但是,EF能够从数据库中获取三个构造函数参数值x.Id, x.Surname, x.Forename
。只有这三个值(Select id, surname, forename from people order by name
):EF Core支持顶层投影中的部分客户端评估(本质上是对Select()的最后一次调用)。如果查询中的顶级投影不能被转换到服务器,EF Core将从服务器获取任何所需的数据,并在客户端上评估查询的剩余部分。如果EF Core在顶级投影之外的任何地方检测到表达式,无法转换到服务器,则会抛出运行时异常
详细说明见
https://learn.microsoft.com/en-us/ef/core/querying/client-eval
文档。测试
下面是EF将顶级投影转换为SQL的示例。表达式:
字符串
生成的sql(对于sqlite):
型