Skip to content
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

fix duplicate join issues #993

Merged
merged 6 commits into from
Aug 10, 2023

Conversation

ElizabethOkerio
Copy link
Contributor

@ElizabethOkerio ElizabethOkerio commented Jul 20, 2023

This issue leads to duplicate joins being generated, like the one below, when we execute such a query RawIncidents?$expand=alerts

SELECT [t].[IncidentId], [t0].[Id], [t1].[AlertId]
FROM (
    SELECT TOP(@__TypedProperty_3) [r].[IncidentId]
    FROM [WcdTestCloudEusStg].[RawIncidents] AS [r]
) AS [t]
LEFT JOIN (
    SELECT [a].[AlertId] AS [Id], [a].[IncidentId]
    FROM [WcdTestCloudEusStg].[AlertsForPublicApi] AS [a]
) AS [t0] ON [t].[IncidentId] = [t0].[IncidentId]
LEFT JOIN (
    SELECT [t2].[AlertId], [t2].[IncidentId]
    FROM (
        SELECT [a0].[AlertId], [a0].[IncidentId], ROW_NUMBER() OVER(PARTITION BY [a0].[IncidentId] ORDER BY [a0].[AlertId]) AS [row]
        FROM [WcdTestCloudEusStg].[AlertsForPublicApi] AS [a0]
    ) AS [t2]
    WHERE [t2].[row] <= @__TypedProperty_1
) AS [t1] ON [t].[IncidentId] = [t1].[IncidentId]
ORDER BY [t].[IncidentId], [t0].[Id], [t1].[IncidentId], [t1].[AlertId]

SelectExpandWrapper uses the Instance property which contains all the properties of a type including the structural and navigation properties. We then again add the navigation properties to the Container property. So it's like the navigation properties get added twice and EF doesn't do deduplication of custom expressions (by design) which leads to duplicate joins being generated.

The solution here was to only write the structural properties to the Instance and leave out the navigation properties which get added to the Container property.

To the ProjectElement method in the SelectExpandBinder class, I have made some updates to ensure that the Instance that gets created is in this form:

{ Instance = new Customer() {Id = $it.Id, Name= $it.Name}}

That's, it only has structural properties.

Another change was to check that the QueryProvider is an EF query provider.. These changes are only done when we are dealing with an EF QueryProvider. If not, then the expression is built the way it has always been built.

Copy link
Contributor

@KenitoInc KenitoInc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some unit tests here

Copy link
Contributor

@habbes habbes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be great to add a test that looks like the customer scenario described in the issue, i.e.: applying OData query options to an IQueryable that is the result of a .Select() mapping from one type to another, where the input comes from a DbSet with an Includes call on a navigation property.

xuzhg
xuzhg previously approved these changes Aug 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants