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.

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions