Suppose you have an Author domain class, and a Book domain class and each Author can have 0 or more Books (a one-to-many relationship).
If you do the following:
var dtos = dbContext.Authors.Select(a => new
{
Name = a.Name,
BookNames = a.Books.Select(b => b.Name).ToList()
}).ToList();
You expect the following SQL to get generated since you only requested the names of the authors, and the names of the books of each author:
SELECT [a].[Name], [b].[Name]
FROM [Authors] AS [a]
LEFT JOIN [Books] AS [b] ON [a].[Id] = [b].[AuthorId]
ORDER BY [a].[Id], [b].[Id]
However, instead, Entity Framework causes the following SQL to be generated:
SELECT [a].[Name], [a].[Id], [b].[Name], [b].[Id]
FROM [Authors] AS [a]
LEFT JOIN [Books] AS [b] ON [a].[Id] = [b].[AuthorId]
ORDER BY [a].[Id], [b].[Id]
which apparently is unnecessarily retrieving the IDs of all authors and the IDs of all their books.
This is while this doesn't happen when you do the joining from the other side, that is, from books to authors. For example, when you request the names of the books, and the names of their authors, like:
var dtos = dbContext.Books.Select(b => new
{
Name = b.Name,
BookNames = b.Author == null ? null : b.Author.Name
}).ToList();
The generated SQL for the above code would be:
SELECT [b].[Name], CASE
WHEN [a].[Id] IS NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END, [a].[Name]
FROM [Books] AS [b]
LEFT JOIN [Authors] AS [a] ON [b].[AuthorId] = [a].[Id]
which is not retrieving the IDs, as expected.
Why is this the case? Why does EF Core retrieve the IDs even though I didn't include them in my projection?
I have tested this with EF Core 3.x + 5.0 RC1. If that matters.