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

System.ArgumentException: must be reducible node when using Include #16987

Closed
amosonn opened this issue Aug 6, 2019 · 10 comments
Closed

System.ArgumentException: must be reducible node when using Include #16987

amosonn opened this issue Aug 6, 2019 · 10 comments

Comments

@amosonn
Copy link

amosonn commented Aug 6, 2019

In preview5, we used the internal .AsAsyncEnumerable() method and wrapped with a generator to convert the Ix.IAsyncEnumerable to the compiler one. When switching to preview7, we got this error:

System.ArgumentException: must be reducible node
   at System.Linq.Expressions.Expression.ReduceAndCheck()
   at System.Linq.Expressions.Expression.ReduceExtensions()
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExtensionExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteUnaryExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression expression)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(ReadOnlyCollection`1 expressions)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteNewArrayExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression expression)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteNewExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpressionFreeTemps(Expression expression, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
   at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
   at System.Linq.Expressions.Compiler.StackSpiller.AnalyzeLambda(LambdaExpression lambda)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteLambdaExpression(Expression expr)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression expression)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression expression)
   at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteNewExpression(Expression expr, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpressionFreeTemps(Expression expression, Stack stack)
   at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
   at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
   at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
   at System.Linq.Expressions.Expression`1.Compile(Boolean preferInterpretation)
   at System.Linq.Expressions.Expression`1.Compile()
   at Microsoft.EntityFrameworkCore.Query.Pipeline.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)
...

This works:

var enumerable = (IAsyncEnumerable<RawNotarizedEventDataModel>)_ctx.NotarizedEvents !;
await using (var enumerator = enumerable.GetAsyncEnumerator()) { ... }

This doesn't:

var enumerable = (IAsyncEnumerable<RawNotarizedEventDataModel>)_ctx.NotarizedEvents.Include(n => n.Definition);
await using (var enumerator = enumerable.GetAsyncEnumerator()) { ... }

Relevant part of entities and context:

public class RawNotarizedEventDataModel
{
    private RawEventTypeDefinitionDataModel? _definition;
    public Guid Id { get; }
    public RawEventTypeDefinitionDataModel Definition { get => _definition!; private set => _definition = value; }
}

public class RawEventTypeDefinitionDataModel
{
    public string Name { get; }
    public int Version { get; }
}

public class EventStoreContext : DbContext
{
    public DbSet<RawNotarizedEventDataModel>? NotarizedEvents { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<RawEventTypeDefinitionDataModel>(b =>
        {
            b.HasKey(d => new { d.Name, d.Version });
        });

        modelBuilder.Entity<RawNotarizedEventDataModel>(b =>
        {
            b.HasKey(ne => ne.Id);
            b.HasOne(ne => ne.Definition).WithMany().IsRequired();
        });
    }
}

Further technical details

EF Core version: 3.0.0-preview7
Database Provider: Npgsql.EntityFrameworkCore.PostgreSQL
Operating system: mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview7

@ajcvickers
Copy link
Member

@amosonn EF Core doesn't use IX Async anymore.

@amosonn
Copy link
Author

amosonn commented Aug 6, 2019

I know; in preview5 it still did, and the point of switching to preview7 was to be able to drop IX and the bridging it required to the builtin types.

@ajcvickers
Copy link
Member

@amosonn Can you give some more details on what you are trying to achieve? Does the query work if used in the normal manner?

@ajcvickers
Copy link
Member

EF Team Triage: Closing this issue as the requested additional details have not been provided and we have been unable to reproduce it.

BTW this is a canned response and may have info or details that do not directly apply to this particular issue. While we'd like to spend the time to uniquely address every incoming issue, we get a lot traffic on the EF projects and that is not practical. To ensure we maximize the time we have to work on fixing bugs, implementing new features, etc. we use canned responses for common triage decisions.

@amosonn
Copy link
Author

amosonn commented Aug 21, 2019

Sorry, I was away for a while and could not respond.
What we are trying to do, is to get an IAsyncEnumerable for a simple (therefore large) query. Apparently, if we just use the DbSet directly it works; if we add the Include directive to get an associated (FK) entity, it breaks.
This did work on preview5, where EFCore still used the Ix.IAsyncEnumerable, and we just wrap it to convert it to the compiler-provided IAsyncEnumerable.

@smitpatel
Copy link
Member

Use extension method on IQueryable which EF Core provides AsAsyncEnumerable. It works exactly like AsEnumerable just gives async enumerable rather than sync one.

var enumerable = _ctx.NotarizedEvents.Include(n => n.Definition).AsAsyncEnumerable();
await using (var enumerator = enumerable.GetAsyncEnumerator()) { ... }

@amosonn
Copy link
Author

amosonn commented Aug 21, 2019

This gives the exact same error as above.

@smitpatel
Copy link
Member

@amosonn - Since you are using Include, it may not work properly in previous previews and in all providers.
Update to latest preview (or even better nightly build) and post a full repro code if you are still seeing the issue.

@amosonn
Copy link
Author

amosonn commented Aug 23, 2019

Upgraded to preview8. Now the stack trace is:

System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Translate(InMemoryQueryExpression queryExpression, Expression expression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
   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.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)
...

(and we don't get this when the Include directive is removed)

@smitpatel
Copy link
Member

Include is not fully functional for InMemory in preview8 builds. Either use provider other than InMemory or try daily builds which has this issue fixed. You can track status of InMemory provider at #16963

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
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