Skip to content

Can no longer client-evaluate query with projection involving non-primitive list #32634

Description

@roji

Code:

await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();

Foo[] foos = [new(3, 4), new(5, 6)];
_ = await ctx.Blogs.Select(b => foos[b.Id].X).ToListAsync();

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
}

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public record Foo(int X, int Y);

Error:

Unhandled exception. System.InvalidOperationException: Expression '@__foos_0' in the SQL tree does not have a type mapping assigned.
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression) in /Users/roji/projects/efcore/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs:line 2911
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression) in /Users/roji/projects/efcore/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs:line 735
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerOpenJsonExpression.VisitChildren(ExpressionVisitor visitor) in /Users/roji/projects/efcore/src/EFCore.SqlServer/Query/Internal/SqlServerOpenJsonExpression.cs:line 75
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RelationalInferredTypeMappingApplier.VisitExtension(Expression expression) in /Users/roji/projects/efcore/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs:line 2917
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQueryableMethodTranslatingExpressionVisitor.SqlServerInferredTypeMappingApplier.VisitExtension(Expression expression) in /Users/roji/projects/efcore/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs:line 735
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.<VisitChildren>g__VisitList|126_0[T](List`1 list, Boolean inPlace, Boolean& changed, <>c__DisplayClass126_0&) in /Users/roji/projects/efcore/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs:line 4850

Previously, we failed to translate this and went into client-evaluation. However, TranslatePrimitiveCollection now attempts to translate the parameterized list. Since it's a parameter, it does not know at that point whether the CLR type is valid or not - it may be an arbitrary user type that gets value converted to a primitive database type (we'd infer that type mapping later, based on how the list's elements are used in the query). However, in this case we obviously cannot infer a type mapping, and throw.

The workaround is simply to force client evaluation by inserting AsEnumerable() just before the projection. Note that this error only occurs when the non-primitive collection parameter is in the top-most Select; inside e.g. a Where translation failed in any case.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions