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

Extracting subquery to a variable causes local evaluation #4857

Closed
jdaley opened this issue Mar 19, 2016 · 1 comment
Closed

Extracting subquery to a variable causes local evaluation #4857

jdaley opened this issue Mar 19, 2016 · 1 comment
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@jdaley
Copy link

jdaley commented Mar 19, 2016

Sorry for the contrived query, it's a simplified example that still reproduces the problem.

If I run this code, it works fine:

var ids = new List<int>() { 3, 4, 5 };

var query =
    from a2 in context.Assets
    where (
        from a1 in context.Assets
        where ids.Contains(a1.Id)
        select a1.Id
    ).Contains(a2.Id)
    select a2;

The generated SQL looks good:

SELECT [a2].[Id], [a2].[Name]
FROM [Asset] AS [a2]
WHERE [a2].[Id] IN (
    SELECT [a1].[Id]
    FROM [Asset] AS [a1]
    WHERE [a1].[Id] IN (3, 4, 5)
)

But if I modify that code to pull the subquery out into a variable...

var ids = new List<int>() { 3, 4, 5 };

var subquery =
    from a1 in context.Assets
    where ids.Contains(a1.Id)
    select a1.Id;

var query =
    from a2 in context.Assets
    where subquery.Contains(a2.Id)
    select a2;

Then EF decides that it "could not be translated and will be evaluated locally":

Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression '{value(System.Collections.Generic.List`1[System.Int32]) => Contains([a1].Id)}' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression 'Contains([a1].Id)' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression 'Contains([a2].Id)' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression '{from Asset a1 in value(Microsoft.Data.Entity.Query.Internal.EntityQueryable`1[Entities.Asset]) where {value(System.Collections.Generic.List`1[System.Int32]) => Contains([a1].Id)} select [a1].Id => Contains([a2].Id)}' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression '{value(System.Collections.Generic.List`1[System.Int32]) => Contains([a1].Id)}' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression 'Contains([a1].Id)' could not be translated and will be evaluated locally.
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Warning: The LINQ expression 'Contains([a2].Id)' could not be translated and will be evaluated locally.

And it repeatedly executes the following query, over and over:

Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a1].[Id]
FROM [Asset] AS [a1]
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a1].[Id]
FROM [Asset] AS [a1]
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a1].[Id]
FROM [Asset] AS [a1]
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a1].[Id]
FROM [Asset] AS [a1]
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a1].[Id]
FROM [Asset] AS [a1]

etc...

The number of times it executes matches the number of rows in the Asset table.

Generally speaking, I would have expected any EF IQueryable variable used within a query to be automatically "inlined", if that makes sense, and produce the same SQL as if it had been written as a single LINQ statement?

7.0.0-rc1-final. Windows 10, VS 2015 LocalDB

@rowanmiller rowanmiller added this to the 1.0.0 milestone Mar 25, 2016
@rowanmiller rowanmiller modified the milestones: 1.0.1, 1.0.0 May 11, 2016
@anpete
Copy link
Contributor

anpete commented Jun 15, 2016

Verified no longer repros.

@anpete anpete closed this as completed Jun 15, 2016
@anpete anpete added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jul 8, 2016
@ajcvickers ajcvickers modified the milestones: 1.1.0-preview1, 1.1.0 Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

No branches or pull requests

4 participants