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

Throw a better exception for failed translations (i.e. client evaluation not supported) #16133

Closed
nixxcz opened this issue Jun 18, 2019 · 6 comments
Labels
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

@nixxcz
Copy link

nixxcz commented Jun 18, 2019

I'm passing a predicate to LINQ query as Func<>. The resulting expression cannot be, for some reason, translated to SQL. In Preview 5, I get a helpful exception. In Preview 6, I get no clue about what went wrong.

#16101 may be related

I would appreciate suggestions on how to pass the predicate so that it can be translated.
Thank you!

Preview 5 behavior

System.InvalidOperationException
  HResult=0x80131509
  Message=Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'where Invoke(__predicate_0, [a], ".cz")' could not be translated and will be evaluated locally.'. This exception can be suppressed or logged by passing event ID 'RelationalEventId.QueryClientEvaluationWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition`1.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, WarningBehavior warningBehavior, TParam arg)
   at Microsoft.EntityFrameworkCore.Diagnostics.RelationalLoggerExtensions.QueryClientEvaluationWarning(IDiagnosticsLogger`1 diagnostics, QueryModel queryModel, Object queryModelElement)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.WarnClientEval(QueryModel queryModel, Object queryModelElement)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database, IDiagnosticsLogger`1 logger, Type contextType)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass17_0`1.<Execute>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.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Vam.Admin.VamData.Playground.Program.Main(String[] args)

Preview 6 behavior

System.InvalidCastException
  HResult=0x80004002
  Message=Unable to cast object of type 'System.Linq.Expressions.InvocationExpression2' to type 'Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions.SqlExpression'.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression)
   at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression expression)
   at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLambdaExpression(ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression)
   at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate)
   at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryCompilationContext2.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery2[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__DisplayClass9_0`1.<Execute>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.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Vam.Admin.VamData.Playground.Program.Main(String[] args)

Steps to reproduce

var context = new VamContext();

Expression<Func<Account, bool>> predicateExpression1 = a => a.Email.Contains(".cz");
var query1 = context.Account.Where(predicateExpression1);
var results1 = query1.ToList(); //OK

Func<Account, string, bool> predicate = (a, filter) => a.Email.Contains(filter);
Expression<Func<Account, bool>> predicateExpression2 = a => predicate(a, ".cz");
var query2 = context.Account.Where(predicateExpression2);
var results2 = query2.ToList(); //Throws exception

Further technical details

Packages

    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview5.19227.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview5.19227.1">

Operating system: Windows 10 Version 10.0.17763 Build 17763
IDE: VS 2019 16.2.0 Preview 2.0

@smitpatel
Copy link
Member

Duplicate of #14572

That being said, second query may not work because of client eval.

@ajcvickers
Copy link
Member

@nixxcz Also, many thanks for trying preview 6. We really appreciate people trying the previews and filing issues on what they find.

If you haven't seen it already, there is some good information in the preview announcement post about the changes that are happening to LINQ queries for EF Core 3.0. Preview 6 is the first release containing these changes, which means we are both expecting things to be broken, but at the same time very grateful for everyone who tries the release and generated feedback.

@nixxcz
Copy link
Author

nixxcz commented Jun 19, 2019

Thanks @smitpatel and @ajcvickers for your replies. Does that mean that the more helpful exception from Preview 5 will be coming back in future versions?

In case anyone is interested, I managed to work around the issue by using LinqKit.Microsoft.EntityFrameworkCore and its Expression.Invoke() and Expression.Expand() extension methods:

Func<Account, string, bool> predicate = (a, filter) => a.Email.Contains(filter); //passed from calling code

Expression<Func<Account, bool>> predicateExpression2 = a => predicate.Invoke(a, ".cz");
var query2 = context.Account.Where(predicateExpression2.Expand());

@divega divega added this to the 3.0.0 milestone Jun 20, 2019
@ajcvickers
Copy link
Member

@nixxcz Not sure when the better exception is coming back, but that is the goal.

@smitpatel
Copy link
Member

SqlTranslator is also supposed to return null on VisitInvocation.

smitpatel added a commit that referenced this issue Jun 21, 2019
Part of #16133
Part of #16144
Resolves #16152
Part of #15662
smitpatel added a commit that referenced this issue Jun 21, 2019
Part of #16133
Part of #16144
Resolves #16152
Part of #15662
smitpatel added a commit that referenced this issue Jun 21, 2019
Part of #16133
Part of #16144
Resolves #16152
Part of #15662
smitpatel added a commit that referenced this issue Jun 21, 2019
Part of #16133
Part of #16144
Resolves #16152
Part of #15662
@smitpatel
Copy link
Member

Fixed SqlTranslator to not throw InvalidCastException.

@smitpatel smitpatel changed the title Preview 6 - unhelpful InvalidCastException thrown when LINQ expression could not be translated Preview 6 - Log exception message when we fail to translate query to server Jun 23, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0, 3.0.0-preview7 Jul 2, 2019
@ajcvickers ajcvickers changed the title Preview 6 - Log exception message when we fail to translate query to server Throw a better exception for failed translations (i.e. client evaluation not supported) Jul 26, 2019
@ajcvickers ajcvickers assigned bricelam and ajcvickers and unassigned bricelam Aug 16, 2019
ajcvickers added a commit that referenced this issue Aug 18, 2019
Fixes #16133 and also partial fix for #15937

This is far from perfect and needs some further work. For example, see #17236

No issues reference #14935 any more; new issues cover things not fixed here but which were refeceing that issue.
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Aug 18, 2019
ajcvickers added a commit that referenced this issue Aug 19, 2019
Fixes #16133 and also partial fix for #15937

This is far from perfect and needs some further work. For example, see #17236

No issues reference #14935 any more; new issues cover things not fixed here but which were refeceing that issue.
ajcvickers added a commit that referenced this issue Aug 19, 2019
Fixes #16133 and also partial fix for #15937

This is far from perfect and needs some further work. For example, see #17236

No issues reference #14935 any more; new issues cover things not fixed here but which were refeceing that issue.
ajcvickers added a commit that referenced this issue Aug 19, 2019
Fixes #16133 and also partial fix for #15937

This is far from perfect and needs some further work. For example, see #17236

No issues reference #14935 any more; new issues cover things not fixed here but which were refeceing that issue.
@ajcvickers ajcvickers reopened this Aug 19, 2019
@ajcvickers ajcvickers removed the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Aug 19, 2019
ajcvickers added a commit that referenced this issue Aug 19, 2019
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Aug 19, 2019
ajcvickers added a commit that referenced this issue Aug 20, 2019
ajcvickers added a commit that referenced this issue Aug 20, 2019
ajcvickers added a commit that referenced this issue Aug 20, 2019
smitpatel pushed a commit that referenced this issue Aug 21, 2019
Fixes #16133 and also partial fix for #15937

This is far from perfect and needs some further work. For example, see #17236

No issues reference #14935 any more; new issues cover things not fixed here but which were refeceing that issue.
smitpatel pushed a commit that referenced this issue Aug 21, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0, 3.0.0-preview9 Aug 21, 2019
@ajcvickers ajcvickers modified the milestones: 3.0.0-preview9, 3.0.0 Nov 11, 2019
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
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. customer-reported type-bug
Projects
None yet
Development

No branches or pull requests

5 participants