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

efcore/NativeAOT: precompile queries throws UnreachableException exception. #35494

Open
dozer75 opened this issue Jan 19, 2025 · 9 comments
Open

Comments

@dozer75
Copy link

dozer75 commented Jan 19, 2025

Question

I am testing efcore and NativeAOT, but when I try to precompile queries using the command dotnet ef dbcontext optimize --precompile-queries --nativeaot it fails with the following callstacks for the LINQ expression _context.MarketDays.Where(md => md.Area == area && md.DeliveryDate == deliveryDate).FirstOrDefaultAsync(cancellationToken)

System.InvalidOperationException: Query precompilation failed with errors:
QueryPrecompilationError { SyntaxNode = _context.MarketDays.Where(md => md.Area == area && md.DeliveryDate == deliveryDate).FirstOrDefaultAsync(cancellationToken), Exception = System.Diagnostics.UnreachableException: IdentifierName of type ParameterSymbol: cancellationToken
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument)
   at Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }
QueryPrecompilationError { SyntaxNode = _context.MarketDays.Where(md => md.Area == area && md.DeliveryDate == deliveryDate).FirstOrDefaultAsync(cancellationToken), Exception = System.Diagnostics.UnreachableException: IdentifierName of type ParameterSymbol: area
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitBinaryExpression(BinaryExpressionSyntax binary)
   at Microsoft.CodeAnalysis.CSharp.Syntax.BinaryExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitBinaryExpression(BinaryExpressionSyntax binary)
   at Microsoft.CodeAnalysis.CSharp.Syntax.BinaryExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitLambdaExpression(AnonymousFunctionExpressionSyntax lambda)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax lambda)
   at Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument)
   at Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }

I get similar errors for all of my queries.

I have followed the documentation at NativeAOT Support and Precompiled Queries (Experimental) and the queries are really simple queries, so I have no idea what I am doing wrong (or if this is an issue with the NativeAOT functionality somehow).

Your code

Stack traces


Verbose output

Using project '<Project>'.
Using startup project '<Project>'.
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\<user>\AppData\Local\Temp\tmpif2evw.tmp /verbosity:quiet /nologo <Project>
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\<user>\AppData\Local\Temp\tmpqvdjt0.tmp /verbosity:quiet /nologo <Project>
Build started...
dotnet build <Project> /verbosity:quiet /nologo /p:PublishAot=false /p:EFOptimizeContext=false

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.12

Workload updates are available. Run `dotnet workload list` for more information.

Build succeeded.
dotnet exec --depsfile <depsfile> --additionalprobingpath C:\Users\<user>\.nuget\packages --additionalprobingpath "C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages" --runtimeconfig <runtimeconfig> C:\Users\<user>\.dotnet\tools\.store\dotnet-ef\9.0.1\dotnet-ef\9.0.1\tools\net8.0\any\tools\netcoreapp2.0\any\ef.dll dbcontext optimize --precompile-queries --nativeaot --assembly <dll> --project <Project> --startup-assembly <dll> --startup-project <project> --project-dir <ProjectDir> --root-namespace <Namespace> --language C# --framework net9.0 --nullable --working-dir <sourcedir> --verbose
Query precompilation is an experimental feature and should be used with caution.
NativeAOT support is experimental and can change in the future.
Using assembly '<assembly>'.
Using startup assembly '<assembly>'.
Using application base '<sourcedir>\bin\Debug\net9.0'.
Using working directory '<sourcedir>'.
Using root namespace '<namespace>'.
Using project directory '<ProjectDir>'.
Remaining arguments: .
Finding DbContext classes...
Using environment 'Development'.
Finding IDesignTimeDbContextFactory implementations...
Finding DbContext classes in the project...
Found DbContext '<context>'.
Finding application service provider in assembly '<assembly>'...
Finding Microsoft.Extensions.Hosting service provider...
Using application service provider from Microsoft.Extensions.Hosting.
Using context '<context>'.
Finding design-time services referenced by assembly '<assembly>'...
Finding design-time services referenced by assembly '<assembly>'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly '<assembly>'...
No design-time services were found.
Successfully generated a compiled model, it will be discovered automatically, but you can also call 'options.UseModel(<context>.Instance)'. Run this command again when the model is modified.
'<context>' disposed.
System.InvalidOperationException: Query precompilation failed with errors:
QueryPrecompilationError { SyntaxNode = _context.MarketDays.Where(md => md.Area == area && md.DeliveryDate == deliveryDate).FirstOrDefaultAsync(cancellationToken), Exception = System.Diagnostics.UnreachableException: IdentifierName of type ParameterSymbol: cancellationToken
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument)
   at Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }
QueryPrecompilationError { SyntaxNode = _context.MarketDays.Where(md => md.Area == area && md.DeliveryDate == deliveryDate).FirstOrDefaultAsync(cancellationToken), Exception = System.Diagnostics.UnreachableException: IdentifierName of type ParameterSymbol: area
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitBinaryExpression(BinaryExpressionSyntax binary)
   at Microsoft.CodeAnalysis.CSharp.Syntax.BinaryExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitBinaryExpression(BinaryExpressionSyntax binary)
   at Microsoft.CodeAnalysis.CSharp.Syntax.BinaryExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitLambdaExpression(AnonymousFunctionExpressionSyntax lambda)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax lambda)
   at Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument)
   at Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }

EF Core version

9.0.1

Database provider

Microsoft.EntityFrameworkCore.SqlServer

Target framework

.NET 9.0

Operating system

Windows 11

IDE

Visual Studio 2022 17.12.3

@dozer75 dozer75 changed the title efcore/NativeAOT: precompile queries throws UnreachableException: exception. efcore/NativeAOT: precompile queries throws UnreachableException exception. Jan 19, 2025
@roji
Copy link
Member

roji commented Jan 19, 2025

@dozer75 thanks for filing, but can you please submit a minimal repro for this? Otherwise it's impossible to know which exact C# construct is causing the exception.

@roji roji self-assigned this Jan 19, 2025
@ChrisJollyAU
Copy link
Contributor

@roji It looks to be something with the cancellation token

You can modify the Terminating_FirstOrDefaultAsync in PrecompiledQueryRelationalTestBase

    [ConditionalFact]
    public virtual Task Terminating_FirstOrDefaultAsyncCancellation()
        => Test(
            """
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Assert.Equal("Blog1", (await context.Blogs.Where(b => b.Id == 8).FirstOrDefaultAsync(token)).Name);
Assert.Null(await context.Blogs.Where(b => b.Id == 7).FirstOrDefaultAsync(token));
""");

Don't forget to add a using System.Threading; to the FullSourceTest function in PrecompiledQueryTestHelpers

@roji
Copy link
Member

roji commented Jan 20, 2025

Thank you @ChrisJollyAU! I can indeed see an error with your proposed test above, but it's not quite the same as what @dozer75 is reporting above:

Precompilation error: System.InvalidOperationException: Encountered unknown identifier name 'token', which doesn't correspond to a lambda parameter or captured variable

@dozer75 as I wrote above, can you please put together a minimal repro for your error?

@roji
Copy link
Member

roji commented Jan 20, 2025

@ChrisJollyAU what you raise is actually a wider bug with any referenced local variables which aren't captured (i.e. in a lambda). I opened #35503 to track this separately, we can continue to use this issue to track the original UnreachableException raised by @dozer75 (where we're waiting for a repro).

@ChrisJollyAU
Copy link
Contributor

@roji Depending on what he is doing with cancellationToken it could be a related issue then (it is failing in the same function). But definitely need more detail

@ChrisJollyAU
Copy link
Contributor

Looking at the VisitIdentifierName function more closely, it looks like maybe the different between what I got and what the original error is, is a matter of where the token was declared (parameter or local).

I have it declared in local, so that switch does handle that but it later fails.
Original problem: cancellationToken looks to have been passed to that scope via parameter. And that switch statement doesn't handle that

@dozer75
Copy link
Author

dozer75 commented Jan 22, 2025

@roji Thanks for noting this issue. I am so sorry for not answering before, I will look into giving you a repo or the code itself, but I am a bit afraid I can't do this before the weekend as there are a lot happening this week...

@dozer75
Copy link
Author

dozer75 commented Jan 22, 2025

@roji I realized that the test project was small so it was easy to strip down, here is a zipped file stripped down to the relevant for the issue. I used dotnet ef dbcontext optimize --precompile-queries --nativeaot as command line. Hope this helps!

slimmed.zip

@roji roji added this to the Backlog milestone Jan 28, 2025
@roji
Copy link
Member

roji commented Jan 28, 2025

Thanks @dozer75, I'll look at it at some point.

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

3 participants