dotnet / dotnet/efcore

Nested query, let clause, select enum issue

Open
#28,170 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

When I try to select an enum column, using an identifier defined by a 'let' clause inside a nested query, I get an exception like the following:

**ArgumentException: Expression of type 'System.Nullable\`1[SolarRecords.Core.Enums.ChecklistItemStatus]' cannot be used for parameter of type 'System.Object' of method 'System.Nullable\`1[System.Int32] Property[Nullable\`1](System.Object, System.String)' (Parameter 'arg0')**

Here is the runnable code to reproduce the problem:

```C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

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

var customerAndChecklistItems = await
(from customer in ctx.Customers
select new
{
ChecklistItems =
(from checklistItem in ctx.ChecklistItems
let customerChecklistItem = customer.CustomerChecklistItems.FirstOrDefault(cstChklstI => cstChklstI.ChecklistItemId == checklistItem.Id)
select new
{
ChecklistItemId = checklistItem.Id,
Status = (ChecklistItemStatus?)customerChecklistItem!.Status,
// The line above throws an exception, but the line below works.
// Status = (ChecklistItemStatus?)customer.CustomerChecklistItems.FirstOrDefault(cstChklstI => cstChklstI.ChecklistItemId == checklistItem.Id)!.Status,
// Note that when selecting a DateTime column, we can use the identifier defined in the 'let' clause without problems.
CompletionDate = customerChecklistItem.CompletionDate
}).ToList()
}).FirstOrDefaultAsync();

public class EfIssueContext : DbContext
{
public DbSet Customers => Set();
public DbSet ChecklistItems => Set();
public DbSet CustomerChecklistItems => Set();

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Server=localhost;Database=test;Integrated Security=true;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity()
.HasKey(customerCheckListItem => new { customerCheckListItem.CustomerId, customerCheckListItem.ChecklistItemId });
}
}

public class Customer
{
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }

public List CustomerChecklistItems { get; } = new();
}

public class ChecklistItem
{
public int Id { get; set; }
public string? Name { get; set; }
}

public class CustomerChecklistItem
{
public int CustomerId { get; set; }
public Customer Customer { get; set; } = null!;
public int ChecklistItemId { get; set; }
public ChecklistItem ChecklistItem { get; set; } = null!;

public ChecklistItemStatus Status { get; set; }
public DateTime? CompletionDate { get; set; }
}

public enum ChecklistItemStatus
{
Pending,
Complete,
NotNeeded
}
```

The Linq query throws this exception:

```
An exception of type 'System.ArgumentException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Expression of type 'System.Nullable`1[ChecklistItemStatus]' cannot be used for parameter of type 'System.Object' of method 'System.Nullable`1[System.Int32] Property[Nullable`1](System.Object, System.String)''
at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Expressions.MethodCallExpression.Update(Expression object, IEnumerable`1 arguments)
at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.Replace(Expression original, Expression replacement, Expression tree)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.RemapLambdaExpression(NavigationExpansionExpression source, LambdaExpression lambdaExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessLambdaExpression(NavigationExpansionExpression source, LambdaExpression lambdaExpression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessWhere(NavigationExpansionExpression source, LambdaExpression predicate)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.MaterializeCollectionNavigationExpression.VisitChildren(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitNew(NewExpression node)
at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PendingSelectorExpandingExpressionVisitor.Visit(Expression expression)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PendingSelectorExpandingExpressionVisitor.Visit(Expression expression)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitNew(NewExpression node)
at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PendingSelectorExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PendingSelectorExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
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__DisplayClass12_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Program.<$>d__0.MoveNext() in C:\SoftwareProjects\TempProjects\EfIssue\Program.cs:line 8
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Program.<$>d__0.MoveNext() in C:\SoftwareProjects\TempProjects\EfIssue\Program.cs:line 8
```

### Provider and version information

EF Core version: 6.0.5
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 11

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.