0

I am trying to map an Enum value (Int16) to an IQueryable projection so that the string representation of the Enum value is used rather than the integer value for the database sorting.

The approach I used was taken from here.

Enum as follows:

    public enum SafetyCategoryEnum : Int16 { High, Medium, Low }

See my AutoMapper mapping below:

config.CreateMap<SupplierContractEntity, SupplierContractEntityWrapper>()
                .ForMember(dest => dest.SafetyCategoryEnumId, 
                opt => { opt.MapFrom(EnumerableExpressionHelper.CreateEnumToStringExpression((SupplierContractEntity e) => e.SafetyCategoryEnumId)); })

SupplierContractEntity is the EntityFramework Entity.

public class SupplierContractEntity : Entity
{
    //Other properties removed for brevity

    public Int16 SafetyCategoryEnumId { get; set; }    
}

SupplierContractEntityWrapper is a custom business object:

public class SupplierContractEntityWrapper : EntityWrapper
{
    //Other properties removed for brevity

  public SafetyCategoryEnum? SafetyCategoryEnumId { get; set; }   
}

Expression mapping is reversed in AutoMapper which is why the Entity maps to the business object

Implementation of CreateEnumToStringExpression:

public static class EnumerableExpressionHelper
{
    public static Expression<Func<TSource, string>> CreateEnumToStringExpression<TSource, TMember>(Expression<Func<TSource, TMember>> memberAccess, string defaultValue = "")
    {
        var type = typeof(SafetyCategoryEnum);
        var enumNames = Enum.GetNames(type);
        var enumValues = (Int16[])Enum.GetValues(type);
        var inner = (Expression)Expression.Constant(defaultValue);
        var parameter = memberAccess.Parameters[0];

        for (int i = 0; i < enumValues.Length; i++)
        {
            inner = Expression.Condition(
            Expression.Equal(memberAccess.Body, Expression.Constant(enumValues[i])),
            Expression.Constant(enumNames[i]), inner);
        }

        MyExpressionVisitor myExpressionVisitor = new MyExpressionVisitor();
        var expression = Expression.Lambda<Func<TSource, string>>(inner, parameter);
        myExpressionVisitor.Visit(expression);
        return expression;
    }
}

When performing a sort AutoMapper throws the following exception:

InvalidOperationException: Rewriting child expression from type 'System.Nullable`1[SafetyCategoryEnum]' to type 'System.String' is not allowed, because it would change the meaning of the operation. 
If this is intentional, override 'VisitUnary' and change it to allow this rewrite.

Is there any way around this type issue?

Any help would be greatly appreciated!

sjr
  • 33
  • 1
  • 4

1 Answers1

0

This works for me with the latest AM, but you need to make the destination a string. I think you're not on the latest version and you've hit an already fixed bug.

Lucian Bargaoanu
  • 3,336
  • 3
  • 14
  • 19