dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.8k stars 3.2k forks source link

'Invalid cast from 'System.Int32' to 'efcore_cosmosdb_bug.OperationStatus'.' - EF Core Azure Cosmos DB Provider #20916

Closed milannankov closed 4 years ago

milannankov commented 4 years ago

I am using the EF Core Azure Cosmos DB Provider and trying to execute a query where I filter based on an enum value but I am getting "'Invalid cast from 'System.Int32' to 'efcore_cosmosdb_bug.OperationStatus'.'" error.

The problem is caused by the Status property of the class InitOperation. There is also a conversion specified in the context but it does not seem to be helping.

The code that breaks is the following:

var result = await context.InitOperations
                .Where(_ => _.Status == OperationStatus.Completed)
                .ToListAsync();

Steps to reproduce

efcore-cosmosdb-bug.zip

I have attached a project that demostrates the problem. Just run the CosmosDb emulator, add the connection settings and run the program.

Exception has occurred: CLR/System.InvalidCastException
An exception of type 'System.InvalidCastException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Invalid cast from 'System.Int32' to 'efcore_cosmosdb_bug.OperationStatus'.'
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.Int32.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType)
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.Sanitize[T](Object value)
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.<>c__DisplayClass3_0`2.<SanitizeConverter>b__0(Object v)
   at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.QuerySqlGenerator.GenerateJToken(Object value, CoreTypeMapping typeMapping)

Further technical details

EF Core version: 3.1.3 Database provider: 3.1.3 Target framework: .NET Core 3.1 Operating system: Windows 7 IDE: Visual Studio Code

ralmsdeveloper commented 4 years ago

@ajcvickers https://github.com/dotnet/efcore/blob/master/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs#L143-L146

Should be?

_partitionKeyValueConverter = partitionKeyProperty.FindTypeMapping()?.Converter 
    ?? partitionKeyProperty.GetValueConverter();
smitpatel commented 4 years ago

This code needs to be in core and more first class (Probably just be part of ValueConverter) https://github.com/dotnet/efcore/blob/98a231faefb919421cfbe50109a2aa59e1dc12c1/src/EFCore.Relational/Storage/RelationalTypeMapping.cs#L453-L457

milannankov commented 4 years ago

Is there a workaround on the framework level that can be used? There is nothing that I could think of besides making temporary changes to classes and directly use int instead of an Enum.