2009-09-14 8 views
2

J'utilise le modèle de visiteur standard pour parcourir une arborescence d'expression LINQ afin de générer des clauses SQL WHERE dynamiques.Comment évaluer une expression booléenne autonome dans un arbre d'expression LINQ

Mon problème est que contrairement à C#, vous ne pouvez pas utiliser une expression booléenne autonome dans SQL; vous devez comparer à 1 ou 0.

Compte tenu de cette hypothétique expression lambda:

h => h.Enabled || h.Enabled == false 

Il serait facile de générer par erreur ce code:

WHERE Enabled OR Enabled = 0 

ou ce code:

WHERE (Enabled = 1) OR (Enabled = 1) = 0 

Les deux vont bien sûr générer une erreur SQL. Quelle logique devrais-je appliquer pour contourner ceci sans que mon code ne commence à sembler vraiment obtus alors que je me penche profondément sur les sous-arbres pour comprendre ce que peut être le cas?

EDIT: L'exemple ci-dessus est bien sûr redondant - je ne l'utilise que pour illustrer un point.

exemples qui pourraient créer ce scénario:

h => h.Enabled 
h => h.Enabled == enabled 
h => h.Enabled == true 

naturellement que le dernier exemple est mauvais style, mais mon code est conçu pour fonctionner indépendamment du niveau de compétence du programmeur, afin de ne pas répondre à des scénarios redondants serait être pauvre forme de ma part.

Répondre

5

Les cas suivants sont assez simple:

h => h.Enabled == enabled 
h => h.Enabled == true 

Ce sont BinaryExpression nœuds, et vous pouvez directement les traduire en:

WHERE (Enabled = @p0) 
WHERE (Enabled = 1) 

Le cas particulier (s) que vous devez gérer sont:

h => h.Enabled 
h => !h.Enabled 

Ceux qui sont représentés différemment dans l'expressio n arbre (en tant que MemberExpression). Donc, vous auriez besoin de cas particulier le MemberExpression et de déterminer si elle accède à une propriété booléenne ou non.Dans ce cas, vous traduisez dans la forme canonique (détection de la UnaryExpression dans le second exemple):

WHERE (Enabled = 1) 
WHERE (Enabled = 0) 

Sinon, vous pourriez être en mesure de pré-traiter l'arbre d'expression et traduisez des cas particuliers dans leur canonique (arbre d'expression) forme. Par exemple, tous les noeuds MemberExpression qui correspondent aux critères peuvent être transformés en BinaryExpression correct.

+0

Salut J'essaie d'atteindre le même. Pourriez-vous s'il vous plaît m'aider à comprendre? Par exemple si dans une expression j'ai 2 expressions booléennes différentes x => x.IsBool || x.IsBool == tue. Si je visite leur MemberExpressions, j'obtiens ce code 'WHERE IsBool = 1 OR IsBool = 1 = 1' qui apparemment est cassé. Comment distinguer une expression de membre a une partie redudante et une autre est explicite? – DolceVita

0

Est-il impossible de traiter complètement les opérandes avant d'éveiller les opérateurs?

Ie. Eval chacun:

h => h.Enabled 
h => h.Enabled == enabled 
h => h.Enabled == true 

à

WHERE (Enabled = 1) 

puis dans le cas où les opérateurs sont inclus dans le lambda, le processus de collecte des opérandes rendus avec SQL équivalent pour répondre aux exigences de l'opérateur.

Questions connexes