New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query: Second level expand not returning correct data #6366
Comments
I also noticed that Roles are not expanded if ordering is by Id (primary key) in query: var query = dbContext.Posts.AsQueryable(); but for example when ordering with another property, ex. OrderBy(x => x.CreatedOn), Roles are expanded correctly |
The problem is not necessarily about the additional JOIN to VoteDefinitions in the second query, but the fact that we are choosing incorrect column to join on between Users and Roles: SELECT [r].[Id], [r].[Name], [r].[UserId]
FROM [Roles] AS [r]
INNER JOIN (
SELECT DISTINCT [t0].*
FROM (
SELECT [v].[Id], [u].[Id] AS [Id0]
FROM [Posts] AS [x]
LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id]
INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id]
ORDER BY [v].[Id], [u].[Id]
OFFSET @__p_0 ROWS
) AS [t0]
) AS [u0] ON [r].[UserId] = [u0].[Id] -- this should be u0.Id0
ORDER BY [u0].[Id], [u0].[Id0] This only seems to be happening for queries with Skip. Without it we produce the following, which works as expected: SELECT [r].[Id], [r].[Name], [r].[UserId]
FROM [Roles] AS [r]
INNER JOIN (
SELECT DISTINCT [v].[Id], [u].[Id] AS [Id0]
FROM [Posts] AS [x]
LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id]
INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id]
) AS [u0] ON [r].[UserId] = [u0].[Id0]
ORDER BY [u0].[Id], [u0].[Id0] |
Yes, this situation is happening if Skip is used (even if Skip(0)). But in case OrderBy is by Id (primary key) then both Roles and PossibleAnswers are not expanded. In case OrderBy(x => X.CreatedOn) which is not a key property(column) then Roles are not expanded but PossibleAnswers are. |
sending back to triage, as it's potentially a candidate for 1.0.1 - in some circumstances we could return invalid data i.e. navigations linked to wrong parent entities |
Problem happens for complex include scenarios like so: ctx .Posts.Include(x => x.User).ThenInclude(x => x.Roles) .Include(x => x.VoteDefinition).ThenInclude(x => x.PossibleAnswers) .Skip(1) We generate 3 queries for this case: - first one gets Posts and 1:1 navigations (User and Vote Definition) SELECT [x].[Id], [x].[Name], [x].[UserId], [x].[VoteDefinitionId], [v].[Id], [v].[PostId], [u].[Id], [u].[Name] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS',N'@__p_0 int - second one copies the first one and joins it with Roles table to return associated Roles SELECT [r].[Id], [r].[Name], [r].[UserId] FROM [Roles] AS [r] INNER JOIN ( SELECT DISTINCT [t0].* FROM ( SELECT [v].[Id], [u].[Id] AS [Id0] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS ) AS [t0] ) AS [u0] ON [r].[UserId] = [u0].[Id] ORDER BY [u0].[Id], [u0].[Id0]',N'@__p_0 int - third one is similar to the second one. Problem is that in second query we are joining based on a wrong column (VoteDefinition's Id rather than User's Id). This is because we lose track of the information about which column is associated with which property. Due to Skip() call in the original LINQ query, we generate SELECT * around the relevant column information. Later, when looking for which column to join, we peek into the SELECT expression and don't see any information there so we assume that we should join based on a property with the name we need. This works fine if there are no duplicate columns with the same name projected out (and uniquefied) from other joined tables. Fix is, in case of a SELECT * query, to look for the relevant column information in the TablesExpressions/SelectExpressions that the SELECT * is projecting from.
Problem happens for complex include scenarios like so: ctx .Posts.Include(x => x.User).ThenInclude(x => x.Roles) .Include(x => x.VoteDefinition).ThenInclude(x => x.PossibleAnswers) .Skip(1) We generate 3 queries for this case: - first one gets Posts and 1:1 navigations (User and Vote Definition) SELECT [x].[Id], [x].[Name], [x].[UserId], [x].[VoteDefinitionId], [v].[Id], [v].[PostId], [u].[Id], [u].[Name] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS',N'@__p_0 int - second one copies the first one and joins it with Roles table to return associated Roles SELECT [r].[Id], [r].[Name], [r].[UserId] FROM [Roles] AS [r] INNER JOIN ( SELECT DISTINCT [t0].* FROM ( SELECT [v].[Id], [u].[Id] AS [Id0] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS ) AS [t0] ) AS [u0] ON [r].[UserId] = [u0].[Id] ORDER BY [u0].[Id], [u0].[Id0]',N'@__p_0 int - third one is similar to the second one. Problem is that in second query we are joining based on a wrong column (VoteDefinition's Id rather than User's Id). This is because we lose track of the information about which column is associated with which property. Due to Skip() call in the original LINQ query, we generate SELECT * around the relevant column information. Later, when looking for which column to join, we peek into the SELECT expression and don't see any information there so we assume that we should join based on a property with the name we need. This works fine if there are no duplicate columns with the same name projected out (and uniquefied) from other joined tables. Fix is, in case of a SELECT * query, to look for the relevant column information in the TablesExpressions/SelectExpressions that the SELECT * is projecting from.
Approved for 1.0.1. |
Problem happens for complex include scenarios like so: ctx .Posts.Include(x => x.User).ThenInclude(x => x.Roles) .Include(x => x.VoteDefinition).ThenInclude(x => x.PossibleAnswers) .Skip(1) We generate 3 queries for this case: first one gets Posts and 1:1 navigations (User and Vote Definition) SELECT [x].[Id], [x].[Name], [x].[UserId], [x].[VoteDefinitionId], [v].[Id], [v].[PostId], [u].[Id], [u].[Name] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS',N'@__p_0 int second one copies the first one and joins it with Roles table to return associated Roles SELECT [r].[Id], [r].[Name], [r].[UserId] FROM [Roles] AS [r] INNER JOIN ( SELECT DISTINCT [t0].* FROM ( SELECT [v].[Id], [u].[Id] AS [Id0] FROM [Posts] AS [x] LEFT JOIN [VoteDefinitions] AS [v] ON [v].[PostId] = [x].[Id] INNER JOIN [Users] AS [u] ON [x].[UserId] = [u].[Id] ORDER BY [v].[Id], [u].[Id] OFFSET @__p_0 ROWS ) AS [t0] ) AS [u0] ON [r].[UserId] = [u0].[Id] ORDER BY [u0].[Id], [u0].[Id0]',N'@__p_0 int third one is similar to the second one. Problem is that in second query we are joining based on a wrong column (VoteDefinition's Id rather than User's Id). This is because we lose track of the information about which column is associated with which property. Due to Skip() call in the original LINQ query, we generate SELECT * around the relevant column information. Later, when looking for which column to join, we peek into the SELECT expression and don't see any information there so we assume that we should join based on a property with the name we need. This works fine if there are no duplicate columns with the same name projected out (and uniquefied) from other joined tables. Fix is, in case of a SELECT * query, to look for the relevant column information in the TablesExpressions/SelectExpressions that the SELECT * is projecting from.
Hello. I noticed bugs in library.
Steps to reproduce
When I try to make query on Posts DbSet with 2 expands of 2. level:
Database model (some properties omitted for clarity):
The issue
This generated bad SQL query resulting in User.Roles not expanded.
Further technical details
As you can see in generated SQL queries, in 2. SQL query, there is line
LEFT JOIN "VoteDefinitions" AS "v" ON "v"."PostId" = "f"."Id"
which should be only in 3. SQL query
SQL generated by this query:
EF Core version: 1.0.0-preview2-final
Operating system: Windows 10 and also Linux Ubuntu
Visual Studio version: VS 2015
The text was updated successfully, but these errors were encountered: