dotnet / dotnet/efcore

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

Open
#32,634 0 comments 0 reactions 1 assignee Claimed by @AndriySvyryd View on GitHub
area-query regression
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Code:

```c#
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 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.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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.