Suppose I perform a query and project into an anonymous type; that would perform evaluation on the server:
var people = await context
.People
.OrderBy(x => x.Name)
.Select(x => new { x.Id, x.Surname, x.Forename })
.ToListAsync();
But suppose I perform a query and need to project into a concrete type.
Option 1: map results into concrete type:
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));
Option 2: use concrete type in "top-level projection":
var people = await context
.People
.OrderBy(x => x.Name)
.Select(x => new PersonDto(x.Id, x.Surname, x.Forename));
.ToListAsync()
About (2), the docs state that in a top-level projection, some evaluation is performed in the database and some on the client. (But the docs show an example of a client function in an anonymous type, so it differs to my use case.)
In this specific example, am I right in assuming that all evaluation is performed on the server, and that (2) is just a short-cut for (1), i.e. they are functionally equivalent?
Question:
all evaluation is performed on the server, and that (2) is just a short-cut for (1), i.e. they are functionally equivalent?
Answer
Obviously, the
PersonDto
object is instantiated on client side, but, EF is able to get the three constructor parameters values,x.Id, x.Surname, x.Forename
from the database. Just this 3 values (Select id, surname, forename from people order by name
):Full explanation at
https://learn.microsoft.com/en-us/ef/core/querying/client-eval
docs.Test
Here a sample of EF translating top-level projection to SQL. Expression:
The generated sql (for sqlite):