2010-09-03 4 views
10

J'essaye de construire dynamiquement un arbre d'expression en C#, qui est compilé et utilisé comme prédicat pour l'appel LINQ-to-SQL Where(). Le problème est que j'essaie de comparer un Enum (avec int comme type sous-jacent) directement à un Int, mais cela échoue avec l'erreur "Le membre MyEnumType n'a pas de traduction supportée par SQL".Comment convertir un Enum en un Int pour une utilisation dans une opération Expression.Equals?

code:

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 

Je suis assez nouveau pour les arbres d'expression et je ne peux pas comprendre cela. J'ai essayé d'utiliser

Expression.Convert(enumMember, typeof(int)) 

comme première partie de l'expression binaire mais cela ne le résout pas.

Toute aide est très appréciée.

+0

ont aucune idée sur la façon d'obtenir la valeur de ENUM dans l'arbre d'expression –

+0

Après un peu plus creuser, j'ai décidé que le problème ici est ma compréhension LINQ to SQL plutôt que avec l'Expression elle-même. La propriété Enum sur mon objet entité n'est pas réellement une colonne dans la base de données; Je pense que c'est pourquoi il n'est pas capable de le traduire en clause where. Je vais adopter une approche différente, mais si quelqu'un a des idées, n'hésitez pas à partager. –

+0

Pouvez-vous également fournir le code pour MyClass? Le code que vous avez actuellement dans le message est assez passif, pas grand chose à dire d'ici ... – code4life

Répondre

0

Essayez

(int) enumMember 
+0

Cela ne compile pas: "Impossible de convertir le type 'System.Linq.Expressions.MemberExpression' en 'int'" –

+0

Heh, Sjoerd serait correct ... si * enumMember * était une énumération réelle et non une abstraction d'un arbre d'expression. –

0

regarder mon premier ami de tout ce que vous devez modifier votre ENUM pour être comme ça:

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

après que vous pouvez convertir entre int et que eunm par cette façon:

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

Cette réponse est une mauvaise compréhension de la question - l'OP veut savoir comment utiliser les arbres d'expression pour travailler avec des types enum. Aussi - enums sont naturellement de type 'int' dans le CLR. Cette question est un résultat de recherche élevé pour les expressions C# avec enums et, en tant que telle, cette réponse devrait être inférieure à la réponse plus appropriée de @philsoady –

6

simplement, vous ne devriez pas avoir à, aussi longtemps que vous avez dit LINQ to SQL sur le ENUM (plutôt que la carte ping en tant que int et ayant une séparée propriété en C# qui fait la traduction). Par exemple, ce qui suit fonctionne très 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(); 

Le point principal est que ma SomeProperty propriété est mappée dans le dbml au ENUM. Il suffit de surclasser le nom du type avec le type enum (y compris l'espace de noms).

De même, vous ne devriez pas lui donner un 1, mais plutôt l'enum tapé; par exemple:

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

(si tout ce que vous connaissez est 1)

1

Merci à Marc Gravell. (Expression Guru!) Voir la bonne réponse. J'ai apporté une modification à une routine d'expression pour répondre à ce scénario. Propriétés normales ou Enums. Incase quelqu'un trouve cela utile

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); 
    } 
Questions connexes