Skip to content

Query :: we are adding redundant navigation joins to query in some cases, resulting in correct but unnecessarily complex queries #6609

@maumar

Description

@maumar

using GearsOfWar model:

                var tags = new List<CogTag>();

                var gears = context.Gears
                    .Where(g => g.Tag != null && tags.Contains(g.Tag.Id))
                    .ToList();

produces the following query model (after navigation expansion)

from Gear g in Gears 
join CogTag g.Tag in CogTags
on 
new CompositeKey(new [] {Convert(Property([g], "Nickname")), Convert(Property([g], "SquadId"))}) 
equals 
new CompositeKey(new [] {Convert(Property([g.Tag], "GearNickName")), Convert(Property([g.Tag], "GearSquadId"))}) 
into IEnumerable`1 g.Tag_group 
from CogTag g.Tag in {[g.Tag_group] => DefaultIfEmpty()} 
join CogTag g.Tag in CogTags) 
on new CompositeKey(new [] {Convert(Property([g], "Nickname")), Convert(Property([g], "SquadId"))}) 
equals 
new CompositeKey(new [] {Convert(Property([g.Tag], "GearNickName")), Convert(Property([g.Tag], "GearSquadId"))}) 
into IEnumerable`1 g.Tag_group 
from CogTag g.Tag in {[g.Tag_group] => DefaultIfEmpty()} 
where (([g.Tag] != null) AndAlso {__tags_0 => Contains([g?.Tag]?.Id)}) 
select [g]

Basically we join CogTag twice even though it's the same reference. Problem is that second time CogTag is used inside a subquery and we are not smart enough to associate those two together. This causes additional join and therefore (currently) additional query issued to the database:

SELECT [g.Tag1].[Id], [g.Tag1].[GearNickName], [g.Tag1].[GearSquadId], [g.Tag1].[Note]
FROM [CogTag] AS [g.Tag1]

SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note]
FROM [Gear] AS [g]
LEFT JOIN [CogTag] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId])
WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND [g.Tag].[Id] IS NOT NULL
ORDER BY [g].[Nickname], [g].[SquadId]

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions