2010-09-03 12 views
10

Estoy intentando construir dinámicamente un árbol de expresiones en C#, que se compila y usa como el predicado de la llamada WhereQ (LINQ-to-SQL). 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 soportada a SQL".¿Cómo convierto un Enum a un Int para usar en una operación Expression.Equals?

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 

yo soy bastante nuevo en los árboles de expresión y no puedo resolver esto. He intentado usar

Expression.Convert(enumMember, typeof(int)) 

como la primera parte de BinaryExpression pero esto no lo arregla.

Cualquier ayuda es muy apreciada.

+0

tienen ni idea sobre el valor de cómo obtener de enumeración en árbol de expresión –

+0

Después de un poco más de excavación, he decidido que el problema aquí es con mi entendimiento LINQ a SQL en lugar de con la Expresión misma. La propiedad Enum en mi objeto entidad no es realmente una columna en la base de datos; Creo que es por eso que no es capaz de traducirlo a una cláusula where. Voy a tomar un enfoque diferente, pero si alguien tiene alguna idea, no dude en compartir. –

+0

¿Puede proporcionar el código para MyClass también? El código que tiene actualmente en la publicación es bastante repetitivo, no hay mucho que contar desde aquí ... – code4life

Respuesta

0

Trate

(int) enumMember 
+0

Esto no compila: "No se puede convertir el tipo 'System.Linq.Expressions.MemberExpression' a 'int'" –

+0

Heh, Sjoerd sería correcto ... si * enumMember * fuera una enumeración real y no una abstracción de árbol de expresiones de uno. –

0

vistazo a mi amigo en primer lugar tiene que modificar su enumeración que ser así:

public enum myenum : int 
{ 
item1 = 0, 
item2 = 1 
} 

después de que se puede convertir entre int y que eunm de esa manera:

int x = (int) myenum.item1; 
+0

Esta respuesta es un claro malentendido de la pregunta: el OP quiere saber cómo usar árboles de expresiones para trabajar con tipos enum. Además, las enumeraciones son naturalmente de tipo 'int' en el CLR. Esta pregunta es un resultado de búsqueda alto para expresiones C# con enumeraciones y, como tal, esta respuesta debe ser menor que la respuesta más adecuada de @philsoady –

6

Simplemente, no debería tener que hacerlo, todo el tiempo que has dicho LINQ a SQL sobre la enumeración (en lugar de un mapa ping como un int y tener una propiedad separada en C# que realiza la traducción). Por ejemplo, la 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 mapea en el dbml a la enumeración. Simplemente sobreescriba el nombre del tipo con el tipo de enumeración (incluido el espacio de nombres).

Del mismo modo, no debería darle un 1, sino la enumeración tipada; por ejemplo:

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

(si todo lo que sabes es 1)

1

Gracias A Marc Gravell. (¡Expresión Guru!) Ver Respuesta correcta. Realicé un cambio en una rutina Expression para atender este escenario. Propiedades normales o Enumeraciones. En caso que alguien encuentre útil esta información

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); 
    } 
Cuestiones relacionadas