¿Cómo convierto un Enum a un Int para usarlo en una operación de Expression.Equals?

c# expression-trees linq-to-sql

Pregunta

Estoy tratando de construir dinámicamente un árbol de expresión en C #, que se compila y usa como predicado para la llamada a LINQ-to-SQL Where (). El problema es que estoy tratando de comparar un Enum (con int como su tipo subyacente) directamente contra un Int, pero esto está fallando con el error "El miembro MyEnumType no tiene traducción compatible con SQL".

Código:

ParameterExpression param = Expression.Parameter(typeof(MyClass), "obj"); //input parameter - this exposes a property of the Enum type
MemberExpression enumMember = Expression.Property(param, "MyEnumProperty"); //used to get the Enum typed property from the parameter

//MISSING STEP TO CAST THE ENUM OF THE MEMBER EXPRESSION TO AN INT?

BinaryExpression binaryExpr = Expression.Equal(enumMember, Expression.Constant(1));
LambdaExpression<Func<MyClass, bool>> whereClause = Expression.Lambda(binaryExpr, param);

//when whereClause is used to filter LINQ-to-SQL results, the error is thrown

Soy bastante nuevo en los árboles de expresión y no puedo entender esto. He intentado usar

Expression.Convert(enumMember, typeof(int))

como la primera parte de la expresión binaria, pero esto no lo arregla.

Cualquier ayuda es muy apreciada.

Respuesta experta

Simplemente, no debería tener que hacerlo, siempre que le haya dicho a LINQ-to-SQL sobre la enumeración (en lugar de asignarla como un int y tener una propiedad separada en C # que haga la traducción). Por ejemplo, lo siguiente funciona bien:

var param = Expression.Parameter(typeof(DomainObject));
var body = Expression.Equal(Expression.Property(param, "SomeProperty"),
                         Expression.Constant(YourEnumType.SomeEnum));
var predicate = Expression.Lambda<Func<DomainObject, bool>>(body, param);
var count = db.Table.Where(predicate).Count();

El punto principal es que mi propiedad SomeProperty se asigna en el dbml a la enumeración. Simplemente sobrescriba el nombre del tipo con el tipo de enumeración (incluido el espacio de nombres).

De la misma manera, no debes darle un 1, sino la enumeración tipificada; por ejemplo:

Expression.Constant(Enum.ToObject(typeof(YourEnumType), 1))

(si todo lo que sabes es 1 )


Respuesta popular

Gracias a Marc Gravell. (¡Expresión gurú!) Ver respuesta correcta. Hice un cambio en una rutina de expresión para atender este escenario. Propiedades normales o enumeraciones. En caso de que alguien encuentre esto útil

public static Expression<Func<TPoco, bool>> GetEqualsPredicate<TPoco>(string propertyName,
                                                                          object value)
                                                                          Type fieldType )
    {     

        var parameterExp = Expression.Parameter(typeof(TPoco), @"t");   //(tpoco t)
        var propertyExp = Expression.Property(parameterExp, propertyName);// (tpoco t) => t.Propertyname

        var someValue = fieldType.IsEnum // get and eXpressionConstant.  Careful Enums must be reduced
                     ? Expression.Constant(Enum.ToObject(fieldType, value)) // Marc Gravell fix
                     : Expression.Constant(value, fieldType);

        var equalsExp = Expression.Equal(propertyExp,  someValue); // yes this could 1 unreadble state if embedding someValue determination

        return Expression.Lambda<Func<TPoco, bool>>(equalsExp, parameterExp); 
    }


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow