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

Improve translation failure exception message for string interpolation #23893

Open
Mike-E-angelo opened this issue Jan 15, 2021 · 3 comments
Open

Comments

@Mike-E-angelo
Copy link

The typical apologies here if this has already been captured. I searched for interpolation in the docs, google, and issues here and did not see anything obvious. The closest I found was #16243 but that appears to be a different issue altogether as the queries I am using (as far as I understand) are not client-evaluated.

In any case, this bugger has taken up a good day's worth of my time in tracking down, so I want to make sure it gets the attention it deserves. :) Luckily I was able to easily reproduce this in a very simple project.

Include your code

This has been posted here for your review:
https://github.com/Mike-E-angelo/Stash/tree/master/EfCore.Interpolation

Note that the difference between the two tests are this line (passes):

https://github.com/Mike-E-angelo/Stash/blob/master/EfCore.Interpolation/EfCore.Interpolation/UnitTest1.cs#L44

vs. this line (fails):

https://github.com/Mike-E-angelo/Stash/blob/master/EfCore.Interpolation/EfCore.Interpolation/UnitTest1.cs#L88

Expected: String interpolation works like string concatenation and does not invoke client projection/evaluation.

Include stack traces

System.InvalidOperationException
Unable to  translate set operation after client projection has been applied. Consider moving the set operation before the last 'Select' call.
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ApplySetOperation(SetOperationType setOperationType, SelectExpression select2, Boolean distinct)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ApplyUnion(SelectExpression source2, Boolean distinct)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   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.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[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToArrayAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at EfCore.Interpolation.UnitTest1.DoesntWork() in ..\Mike-E-angelo\Stash\EfCore.Interpolation\EfCore.Interpolation\UnitTest1.cs:line 91
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass48_1.<<InvokeTestMethodAsync>b__1>d.MoveNext() in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\Runners\TestInvoker.cs:line 264
--- End of stack trace from previous location ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in C:\Dev\xunit\xunit\src\xunit.core\Sdk\ExceptionAggregator.cs:line 90

Include provider and version information

EF Core version: 5.0.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5.0
Operating system: Windows 10 2004 19041.746
IDE: Visual Studio 2019 16.8.4

@ajcvickers
Copy link
Contributor

@Mike-E-angelo The concatenation can be translated, but the interpolation version cannot. This is because interpolation can contain custom formatting that would require complex parsing and even then might not translate to SQL. Do you have ideas on what could we change about the exception thrown that would make this easier to understand?

@Mike-E-angelo
Copy link
Author

Thank you for the explanation @ajcvickers. That makes sense now that it's no longer terrorizing my whole day and I can think a little clearer. 😆

As for remedy, I would certainly appreciate seeing a message saying that interpolation is a (currently 😁) unsupported feature and to use concatenation instead. Perhaps an additional link back to this issue and/or documentation would be valuable as well.

BTW, besides this little hiccup, everything has been really running well with your product. I especially am in awe at the amazing queries you all are pumping out (I figured out how to enable logging around them and it's been super insightful) ... but I am perhaps even more appreciative that I don't have to write them! The speed/performance is great, too. I have written some seriously involved Linq/compiled/expression queries and was so pleasantly surprised to find that they only take a few ms after being passed to Sql Server. So impressive. Very cool stuff over there.

@ajcvickers
Copy link
Contributor

Thanks @Mike-E-angelo. Putting this on the backlog to improve the exception message here.

@ajcvickers ajcvickers added this to the Backlog milestone Jan 19, 2021
@roji roji changed the title Set Operation with Query Containing String Interpolation Produces Unexpected Exception Improve translation failure exception message for string interpolation Jan 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants