Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update from 2.0 to 2.1.1: InvalidCastException when casting to/from enum in query. #12557

Closed
koen-debacker opened this issue Jul 5, 2018 · 3 comments
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@koen-debacker
Copy link

koen-debacker commented Jul 5, 2018

In EF Core 2.0 queries like these would work:
(Status is an enum)

int status = 1;

context.Employees
    .Where(e => (int)e.Status == status)
    .ToList();

context.Employees
    .Where(e => e.Status == (Status)status)
    .ToList();

However, after updating to EF Core 2.1.1 I get the following exception:

Message:
Invalid cast from 'System.Int32' to 'EFCoreTest.Status'.

Stacktrace:
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   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.Storage.RelationalTypeMapping.CreateParameter(DbCommand command, String name, Object value, Nullable`1 nullable)
   at Microsoft.EntityFrameworkCore.Storage.Internal.TypeMappedRelationalParameter.AddDbParameter(DbCommand command, Object value)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalParameterBase.AddDbParameter(DbCommand command, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.CreateCommand(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at EFCoreTest.Program.Main(String[] args) in C:\Users\koen.debacker\Source\repos\EFCoreTest\EFCoreTest\Program.cs:line 13

Steps to reproduce

Project: EFCoreTest.zip

    public class TestContext : DbContext
    {
        public DbSet<Employee> Employees { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=EFCoreTest;Trusted_Connection=True;MultipleActiveResultSets=true;");
        }
    }

    public class Employee
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public Status Status { get; set; }
    }

    public enum Status
    {
        Inactive = 0,
        Active = 1
    }
    class Program
    {
        static void Main(string[] args)
        {
            var context = new TestContext();

            int status = 1;

            context.Employees
                .Where(e => (int)e.Status == status)
                .ToList();

            context.Employees
                .Where(e => e.Status == (Status)status)
                .ToList();
        }
    }

Further technical details

EF Core version: 2.1.1
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2017 15.7.4

@ajcvickers
Copy link
Member

Triage: marking this as investigation for patch since the scenario is simple and it is a regression.

ajcvickers added a commit that referenced this issue Jul 6, 2018
Fixes #12557

This is a simple case that used to work for enums because they were always converted to their underlying type anyway. However, it falls out of the space where normal value converters would be expected to work, so to bring back the old behavior we check if the parameter type is already the underlying type for enum conversions and, if so, don't try to convert it.
@AndriySvyryd AndriySvyryd added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jul 12, 2018
AndriySvyryd added a commit that referenced this issue Jul 12, 2018
roji added a commit to npgsql/efcore.pg that referenced this issue Oct 18, 2018
roji added a commit to npgsql/efcore.pg that referenced this issue Oct 18, 2018
@mmjsd
Copy link

mmjsd commented Apr 23, 2020

This issue has reappeared and the sample program also fails on EF Core 3.1.3. I've attached an
updated solution.
EFCoreTest.zip

@ajcvickers
Copy link
Member

@mmjsd I am able to repro this on 3.1.3. It looks like it is fixed by #19128 which will be released in 3.1.4. It's also fixed in EF Core 5.0 preview 3 which is already available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Projects
None yet
Development

No branches or pull requests

4 participants