dotnet / dotnet/efcore

'Argument types do not match' when selecting off of a projection with a null check

Open
#34,411 1 comment 0 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Repro: https://github.com/MrZander/ProjectionArgExceptionRepro/tree/no-automapper

I have the following queries:
```csharp
//Works
var test1 = context.Entities
.Select(f => new DtoEntity()
{
ID = f.ID,
Type = new DtoEntityType()
{
ID = f.Type.ID,
Tags = f.Type.Tags.Select(t => new DtoTag() { ID = t.ID })
}
})
.Select(f => new FinalResult
{
Value = f.Type.Tags.Count()
})
.Single();
Console.WriteLine(test1.Value);

//Exception
var test2 = context.Entities
.Select(f => new DtoEntity()
{
ID = f.ID,
Type = f.Type == null ? null : new DtoEntityType()
{
ID = f.Type.ID,
Tags = f.Type.Tags.Select(t => new DtoTag() { ID = t.ID })
}
})
.Select(f => new FinalResult
{
Value = f.Type.Tags.Count()
})
.Single();
Console.WriteLine(test2.Value);
```
The only difference is the null check in the second query `f.Type == null ? null : new DtoEntityType()`
The top query executes as expected, the bottom query throws this exception:
```
System.ArgumentException
HResult=0x80070057
Message=Argument types do not match
Source=System.Linq.Expressions
StackTrace:
at System.Linq.Expressions.Expression.Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitConditional(ConditionalExpression conditionalExpression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
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 Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
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__DisplayClass9_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at Program.Main(String[] args) in C:\\ProjectionArgExceptionRepro\ProjectionArgExceptionRepro\Program.cs:line 101
```

The expected result would be that the two queries result in identical execution.
My hunch is that whatever internal mechanism is determining nullability is getting confused by the null check on that the EntityType.

EF Core version: 8.0.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer (The repro uses in-memory for ease of replication)
Target framework: .NET 8.0
Operating system: Windows 10
IDE:Visual Studio 2022 17.10.3

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.