Mixing Select() and Include()
Last week I have been reviewing some code of one of our newer projects. I noticed that for some projections, also Include() was used:
var query = dbContext.Registrations
.Include(registration => registration.CreateUser)
.ThenInclude(user => user.Language)
.Select(registration => new
{
RegistrationNumber = registration.RegistrationNumber,
CreateUserLanguageCode = registration.CreateUser.Language.Code
});
var list = await query.ToListAsync();
Since I never did it like that before I analyzed the SQL-query that was generated:
SELECT [r].[RegistrationNumber], [l].[Code] AS [CreateUserLanguageCode]
FROM [Registrations] AS [r]
INNER JOIN [Users] AS [u] ON [r].[CreateUserId] = [u].[Id]
LEFT JOIN [Languages] AS [l] ON [u].[LanguageCode] = [l].[Code]
The SQL-query looks totally fine and it’s also working. There are no unnecessary subqueries.
But Entity Framework is smart enough to make the required joins that are required inside the Select() on its own. Therefor I removed the Includes:
var query = dbContext.Registrations
.Select(registration => new
{
RegistrationNumber = registration.RegistrationNumber,
CreateUserLanguageCode = registration.CreateUser.Language.Code
});
As expected, after generating the SQL-query there is no difference!
But what if we use Includes when they are not required for our projection? I changed the code to analyze if there will be any unnecessary joins which might affect performance:
var query = dbContext.Registrations
.Include(registration => registration.CreateUser)
.ThenInclude(user => user.Language)
.Select(registration => new
{
RegistrationNumber = registration.RegistrationNumbe
});
As you can see the line which required two joins has been removed. But there are still two unnecessary Includes. The generated SQL-query looks like this:
SELECT [r].[RegistrationNumber]
FROM [Registrations] AS [r]
This proves that Include() will be ignored when also using Select().
Conclusion
There is no real danger in mixing Include() with Select(), at least since Entity Framework Core 6. But unnecessary code is harder to understand and maintain. Therefor it should not be mixed.