提问人:lonix 提问时间:11/12/2023 更新时间:11/13/2023 访问量:43
顶级 EF Core 投影中的客户端评估
Client evaluation in top-level EF Core projection
问:
假设我执行查询并投影到匿名类型中;这将在服务器上执行评估:
var people = await context
.People
.OrderBy(x => x.Name)
.Select(x => new { x.Id, x.Surname, x.Forename })
.ToListAsync();
但是假设我执行一个查询,并且需要投影到具体类型中。
选项 1:将结果映射到具体类型:
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赞
dani herrera
11/12/2023
#1
问题:
所有评估都在服务器上执行,而 (2) 只是 (1) 的捷径,即它们在功能上是等效的?
答
显然,该对象是在客户端实例化的,但是,EF 能够从数据库中获取三个构造函数参数值。只有这 3 个值 ( ):PersonDto
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 的示例。表达:
var result =
dbcontext.
Customers.
Select(x => new PersonName2CharsDto(x.Name.Substring(0,2))).
ToList();
生成的 sql(用于 sqlite):
SELECT substr("c"."Name", 0 + 1, 2)
FROM "Customers" AS "c"
评论
SELECT
SELECT