-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Description
When using Join with an anonymous type result selector on IRewritableQueryable<T>, the generated interceptor code contains invalid type references and fails to compile.
Reproduction
db.Orders
.WithExpressionRewrite()
.Join(db.Customers,
o => o.CustomerId,
c => c.Id,
(o, c) => new { o.Id, CustomerName = c.Name }) // anonymous result
.ToListAsync();Error: Generated code references anonymous type directly instead of using generic type parameters (TResult).
Root Cause
EmitJoin only has a concrete-type code path. It doesn't have the anonymous-type handling branch that EmitSelectMany3 has (lines 619-653) — where anonymous types are mapped to generic type parameters via typeAliases and the method signature uses <TElem, TInner, TKey, TResult>.
Workaround
Use a named type (record/class/struct) instead of an anonymous type:
record OrderCustomer(int Id, string CustomerName);
db.Orders.WithExpressionRewrite()
.Join(db.Customers, o => o.CustomerId, c => c.Id,
(o, c) => new OrderCustomer(o.Id, c.Name))
.ToListAsync();Fix
Add an anonymous-type branch to EmitJoin following the EmitSelectMany3 pattern: detect anonymous types in typeArgs, create typeAliases, generate generic type parameters, and emit (object) casts in the body.
Found via stress test in samples/EFCoreSample/StressTest.cs.