Skip to content

Commit

Permalink
Convert integral value to enum value when printing Sql literal (#16692)
Browse files Browse the repository at this point in the history
In new query pipeline, we preserve convert nodes around enum in expression tree and remove them on both sides when translating to server.
The typeMapping for enum column expects an enum value for constant or parameter
- With new pipeline, we will have parameter's value to be enum so we no longer need any additional code for conversion
- For constants, there is no convert node around constant in actual tree so we are left with integral value to be printed with Enum type mapping. Hence we need to convert it to actual enum value first. Afterwards, provider can print enum literal or apply appropriate conversions
  • Loading branch information
smitpatel authored Jul 22, 2019
1 parent 0960051 commit 9cc38f6
Showing 1 changed file with 11 additions and 25 deletions.
36 changes: 11 additions & 25 deletions src/EFCore.Relational/Storage/RelationalTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,7 @@ public virtual DbParameter CreateParameter(
parameter.Direction = ParameterDirection.Input;
parameter.ParameterName = name;

if (Converter != null
&& !IsLegacyEnumValue(Converter, value))
if (Converter != null)
{
value = Converter.ConvertToProvider(value);
}
Expand All @@ -458,23 +457,6 @@ public virtual DbParameter CreateParameter(
return parameter;
}

// Avoid converting value from enum to integer if it is already an integer; preserves 2.0 behavior
private static bool IsLegacyEnumValue(ValueConverter converter, object value)
=> value != null
&& IsLegacyInteger(value.GetType())
&& converter.GetType().IsGenericType
&& converter.GetType().GetGenericTypeDefinition() == typeof(EnumToNumberConverter<,>);

private static bool IsLegacyInteger(Type type)
{
type = type.UnwrapNullableType();

return type == typeof(int)
|| type == typeof(long)
|| type == typeof(short)
|| type == typeof(byte);
}

/// <summary>
/// Configures type information of a <see cref="DbParameter" />.
/// </summary>
Expand All @@ -492,14 +474,18 @@ protected virtual void ConfigureParameter([NotNull] DbParameter parameter)
/// </returns>
public virtual string GenerateSqlLiteral([CanBeNull] object value)
{
if (Converter != null)
// Enum when compared to constant will always have constant of integral type
// when enum would contain convert node. We remove the convert node but we also
// need to convert the integral value to enum value.
// This allows us to use converter on enum value or print enum value directly if supported by provider
if (value?.GetType().IsInteger() == true
&& ClrType.UnwrapNullableType().IsEnum)
{
if (value?.GetType().IsInteger() == true
&& ClrType.UnwrapNullableType().IsEnum)
{
value = Enum.ToObject(ClrType.UnwrapNullableType(), value);
}
value = Enum.ToObject(ClrType.UnwrapNullableType(), value);
}

if (Converter != null)
{
value = Converter.ConvertToProvider(value);
}

Expand Down

0 comments on commit 9cc38f6

Please sign in to comment.