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

Lazy loading proxy comparison throws"could not be translated" InvalidOperationException #19676

Closed
morganbr opened this issue Jan 23, 2020 · 4 comments · Fixed by #20447
Closed
Assignees
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@morganbr
Copy link

morganbr commented Jan 23, 2020

A where clause comparing a lazy loading proxy to a navigation property of a table is throwing an InvalidOperationException like the one below on .NET Core 3.0 and 3.1. This worked on .NET Core 2.1. While it's possible to work around this by replacing a particular instance with a key comparison, tracking down all of the instances in our project would be a lot of work.

The error also suggests that EF is trying to do a join instead of just comparing the proxy's primary key to the child table's foreign key.

The query is:

 var eventTeams = await (from Team team in _context.Teams
      where team.Event == myEvent // proxy fetched by a previous query
      select team).ToListAsync();

The types involved are a simple parent-child relationship:

    public class Event
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        // other columns
    }

    public class Team
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        // The event the team is a part of
        public int EventID { get; set; }

        // The event the team is a part of
        [Required]
        public virtual Event Event { get; set; }

        // Other columns
    }

The full exception is:

  'The LINQ expression 'Where<TransparentIdentifier<Team, Event>>(
    source: Join<Team, Event, Nullable<int>, TransparentIdentifier<Team, Event>>(
        outer: Cast<Team>(DbSet<Team>), 
        inner: DbSet<Event>, 
        outerKeySelector: (e) => Property<Nullable<int>>(e, "EventID"), 
        innerKeySelector: (e0) => Property<Nullable<int>>(e0, "ID"), 
        resultSelector: (o, i) => new TransparentIdentifier<Team, Event>(
            Outer = o, 
            Inner = i
        )), 
    predicate: (e) => e.Inner == (Unhandled parameter: __myEvent_0))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'
  at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|8_0(ShapedQueryExpression translated, <>c__DisplayClass8_0& )
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__64`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

Further technical details

EF Core version: 3.1
Database provider:Microsoft.EntityFrameworkCore.SqlServer
Target framework: 3.1
Operating system: Windows 10
IDE: Visual Studio 2019 16.4.3

@morganbr
Copy link
Author

It turns out this only repros if you put the type of the variable in the LINQ query, so this works:

var eventTeams = from team in _context.Teams
where team.Event == Event
select team;

But this doesn't

var eventTeams = from Team team in _context.Teams
where team.Event == Event
select team;

Calling query extension methods directly also works.

@smitpatel
Copy link
Contributor

Given Event is an entityType, the where predicate in exception message should have been re-written into entity equality.
cc: @roji

@roji
Copy link
Member

roji commented Feb 6, 2020

We can add it to my pile of EE issues.

@smitpatel smitpatel assigned roji and unassigned ajcvickers and smitpatel Feb 7, 2020
@smitpatel smitpatel assigned smitpatel and unassigned roji Mar 6, 2020
@smitpatel
Copy link
Contributor

related #20164

@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Mar 28, 2020
smitpatel added a commit that referenced this issue Mar 28, 2020
Resolves #15080
Implemented behavior:
- If any part of composite key is null then key is null.
- If comparing entity with null then check if "any" key value is null.
- If comparing entity with non-null then check if "all" key values are non null.

Resolves #20344
Resolves #19431
Resolves #13568
Resolves #13655
Since we already convert property access to nullable, if entity from client is null, make key value as null.

Resolves #19676
Clr type mismatch between proxy type and entity type is ignored.

Resolves #20164
Rewrites entity equality during translation

Part of #18923
smitpatel added a commit that referenced this issue Mar 28, 2020
Resolves #15080
Implemented behavior:
- If any part of composite key is null then key is null.
- If comparing entity with null then check if "any" key value is null.
- If comparing entity with non-null then check if "all" key values are non null.

Resolves #20344
Resolves #19431
Resolves #13568
Resolves #13655
Since we already convert property access to nullable, if entity from client is null, make key value as null.

Resolves #19676
Clr type mismatch between proxy type and entity type is ignored.

Resolves #20164
Rewrites entity equality during translation

Part of #18923
smitpatel added a commit that referenced this issue Mar 28, 2020
Resolves #15080
Implemented behavior:
- If any part of composite key is null then key is null.
- If comparing entity with null then check if "any" key value is null.
- If comparing entity with non-null then check if "all" key values are non null.

Resolves #20344
Resolves #19431
Resolves #13568
Resolves #13655
Since we already convert property access to nullable, if entity from client is null, make key value as null.

Resolves #19676
Clr type mismatch between proxy type and entity type is ignored.

Resolves #20164
Rewrites entity equality during translation

Part of #18923
smitpatel added a commit that referenced this issue Mar 31, 2020
Resolves #15080
Implemented behavior:
- If any part of composite key is null then key is null.
- If comparing entity with null then check if "any" key value is null.
- If comparing entity with non-null then check if "all" key values are non null.

Resolves #20344
Resolves #19431
Resolves #13568
Resolves #13655
Since we already convert property access to nullable, if entity from client is null, make key value as null.

Resolves #19676
Clr type mismatch between proxy type and entity type is ignored.

Resolves #20164
Rewrites entity equality during translation

Part of #18923
smitpatel added a commit that referenced this issue Mar 31, 2020
Resolves #15080
Implemented behavior:
- If any part of composite key is null then key is null.
- If comparing entity with null then check if "any" key value is null.
- If comparing entity with non-null then check if "all" key values are non null.

Resolves #20344
Resolves #19431
Resolves #13568
Resolves #13655
Since we already convert property access to nullable, if entity from client is null, make key value as null.

Resolves #19676
Clr type mismatch between proxy type and entity type is ignored.

Resolves #20164
Rewrites entity equality during translation

Part of #18923
@ajcvickers ajcvickers modified the milestones: 5.0.0, 5.0.0-preview3 Mar 31, 2020
@smitpatel smitpatel modified the milestones: 5.0.0-preview3, 5.0.0 Apr 1, 2020
@ajcvickers ajcvickers modified the milestones: 5.0.0, 5.0.0-preview4 Apr 20, 2020
@ajcvickers ajcvickers removed this from the 5.0.0-preview4 milestone Nov 7, 2020
@ajcvickers ajcvickers added this to the 5.0.0 milestone Nov 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants