Skip to content

EF Core InMemory database throws an argument exception on Nullable<>.ToString #35299

@wilfriedb

Description

@wilfriedb

After upgrading to EF Core 9, a unit test using the InMemory database throws this exception:

System.ArgumentException
  HResult=0x80070057
  Message=Method 'System.String ToString(System.String)' declared on type 'System.DateOnly' cannot be called with instance of type 'System.Nullable`1[System.DateOnly]'
  Source=System.Linq.Expressions
  StackTrace:
   at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method) in /_/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs:line 1265

This is from the Microsoft.EntityFrameworkCore.InMemory package.

When I look into this package code where the exception originates, I see the following change between version 8 and version 9:

EF Core 8:
Namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal
InMemoryExpressionTranslatingExpressionVisitor.cs line 888:

        // if object is nullable, add null safeguard before calling the function
        // we special-case Nullable<>.GetValueOrDefault, which doesn't need the safeguard
        if (methodCallExpression.Object != null
            && @object!.Type.IsNullableType()
            && methodCallExpression.Method.Name != nameof(Nullable<int>.GetValueOrDefault))
        {

EF Core 9:
InMemoryExpressionTranslatingExpressionVisitor.cs line 887:

        // if object is nullable, add null safeguard before calling the function
        // we special-case Nullable<>.GetValueOrDefault, which doesn't need the safeguard,
        // and Nullable<>.ToString when the object is a nullable value type.
        if (methodCallExpression.Object != null
            && @object!.Type.IsNullableType()
            && methodCallExpression.Method.Name != nameof(Nullable<int>.GetValueOrDefault)
            && (!@object!.Type.IsNullableValueType()
                || methodCallExpression.Method.Name != nameof(Nullable<int>.ToString)))

So the new code adds explicitly a Nullable<>.ToString according to the comment, but this new code throws an exception at runtime because it cannot be called!

(For using an EF Core InMemory database in a unit test, yes I know that's not a good practice, but we inherited this Solution)

The Microsoft.EntityFrameworkCore.SqlServer package does not have this bug, it exhibits the expected behavior.

This seems a regression to me.. It is also interesting to see that the code makes an exception for the int value type, but not for any other value type.

EF Core version: 9.0
Database provider: Microsoft.EntityFrameworkCore.InMemor
Target framework: .NET 0.0)
Operating system: Windows 11 21H2
IDE: Visual Studio 2022 17.12.3

Metadata

Metadata

Assignees

Type

No fields configured for Bug.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions