efcore: Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type
Steps to reproduce
I have the following query:
result.Items = await query.Select(a => new MedicalReportSectionListView()
{
Id = a.Id,
OperatorId = a.OperatorId,
Name = a.Name,
Order = a.Order,
DefaultContent = a.DefaultContent,
Hidden = (a.Flags & MedicalReportSectionFlags.Private) != 0,
Active = (a.Flags & MedicalReportSectionFlags.Active) != 0
}).ToArrayAsync();
the issue is in:
Hidden = (a.Flags & MedicalReportSectionFlags.Private) != 0,
Entity:
[Flags]
public enum MedicalReportSectionFlags
{
None = 0x0,
Active = 0x1,
Private = 0x2,
Attachment= 0x4
}
public class MedicalReportSection
{
[Key]
public int Id { get; set; }
public Guid OperatorId { get; set; }
public string Name { get; set; }
public int Order { get; set; }
public string DefaultContent { get; set; }
public virtual Operator Operator { get; set; }
public MedicalReportSectionFlags Flags { get; set; }
}
Model:
public class MedicalReportSectionListView
{
public int Id { get; set; }
public Guid OperatorId { get; set; }
public string Name { get; set; }
public int Order { get; set; }
public string DefaultContent { get; set; }
public bool Hidden { get; set; }
public bool Active { get; set; }
}
Stack trace:
System.InvalidCastException
HResult=0x80004002
Message=Invalid cast from 'System.Int32' to 'DocSpecial.Data.Entities.MedicalReportSectionFlags'.
Source=System.Private.CoreLib
StackTrace:
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.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.RelationalCommand.CreateCommand(RelationalCommandParameterObject parameterObject, Guid commandId, DbCommandMethod commandMethod)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.<ExecuteReaderAsync>d__17.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.<InitializeReaderAsync>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.<MoveNextAsync>d__17.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__64`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__64`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToArrayAsync>d__65`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at DocSpecial.Core.MedicalReportSectionListHandler.<ExecuteWorkAsync>d__0.MoveNext() in D:\Development\IctMakers\Git\DocSpecial\DocSpecial.Core\Commands\MedicalReportSectionListHandler.cs:line 42
This exception was originally thrown at this call stack:
System.Convert.DefaultToType(System.IConvertible, System.Type, System.IFormatProvider)
int.System.IConvertible.ToType(System.Type, System.IFormatProvider)
System.Convert.ChangeType(object, System.Type, System.IFormatProvider)
System.Convert.ChangeType(object, System.Type)
Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping.CreateParameter(System.Data.Common.DbCommand, string, object, bool?)
Microsoft.EntityFrameworkCore.Storage.Internal.TypeMappedRelationalParameter.AddDbParameter(System.Data.Common.DbCommand, object)
Microsoft.EntityFrameworkCore.Storage.Internal.RelationalParameterBase.AddDbParameter(System.Data.Common.DbCommand, System.Collections.Generic.IReadOnlyDictionary<string, object>)
Microsoft.EntityFrameworkCore.Storage.RelationalCommand.CreateCommand(Microsoft.EntityFrameworkCore.Storage.RelationalCommandParameterObject, System.Guid, Microsoft.EntityFrameworkCore.Diagnostics.DbCommandMethod)
...
[Call Stack Truncated]
Thanks
Further technical details
EF Core version: 5.0.0-alpha1.19552.2 - 3.1.0-preview3.19554.8 Database provider: SqlServer Target framework: .NET Core 3.1 Operating system: Windows 10 - 1903 IDE: Visual Studio 2019 Preview 16.4.0 Preview 6.0
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 6
- Comments: 24 (14 by maintainers)
Commits related to this issue
- Simple command-line app to recreate EF Core bug: https://github.com/dotnet/efcore/issues/19128 — committed to blayvant/efcore-bitflag-bug by blayvant 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #19128 - Query: Error for queries with enum parameters whose value is of underlying type but the value expected by type mapping is the actual enum type Problem was that we were not correctly c... — committed to dotnet/efcore by maumar 4 years ago
bringing back to triage so we can discuss if it meets the bar for patch
This one is quite interesting.
Simplified repro:
What’s happening here is that during parameter extraction, we parameterize argument to the skip method (int = 1), which we always do. However, because the value of
MedicalReportSectionFlags.Active
is also int = 1, it also gets parameterized, and the same parameter is assigned. So after parameter extraction we have the following:When this gets translated to sql we get:
However, the type mapping of parameter in the projection is sql int, backed by clr MedicalReportSectionFlags (inferred from the column). When we visit the projection, this is the parameter that gets added to Parameters collection on RelationalCommand. However the parameterValues contains a value typed as clr int, so when we try to add that value to the parameter collection, exception is thrown