Comment évaluer une expression booléenne autonome dans un arbre d'expression LINQ

c# expression-trees lambda linq

Question

J'utilise le modèle de visiteur standard pour effectuer une itération dans une arborescence d'expression LINQ afin de générer des clauses SQL WHERE dynamiques.

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

Étant donné cette expression hypothétique lambda:

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

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

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

ou ce code:

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

Bien sûr, les deux vont générer une erreur SQL. Quelle logique devrais-je appliquer pour résoudre ce problème sans que mon code commence à paraître vraiment obtus alors que je fouille dans 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 pouvant créer ce scénario:

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

Naturellement, ce dernier exemple est un style médiocre, mais mon code est conçu pour fonctionner indépendamment du niveau de compétence du programmeur. Par conséquent, ne pas prendre en compte les scénarios redondants serait une mauvaise forme de ma part.

Réponse acceptée

Les cas suivants sont assez simples:

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

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

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

Les cas particuliers que vous devez gérer sont:

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

Ceux-ci sont représentés différemment dans l'arbre d'expression (en tant que MemberExpression ). Donc, vous auriez besoin de cas spécial MemberExpression et de déterminer s'il accède ou non à une propriété booléenne. Si c'est le cas, traduisez-le sous la forme canonique (en détectant l' UnaryExpression dans le deuxième exemple):

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

Vous pouvez également pré-traiter l’arbre d’expression et traduire les cas particuliers dans leur forme canonique (arborescence d’expression). Par exemple, tout nœud MemberExpression correspondant aux critères peut être transformé en l' BinaryExpression appropriée.


Réponse populaire

N'est-il pas possible de traiter complètement les opérandes avant d'élever les opérateurs?

C'est à dire. Eval chacune de:

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

à

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

puis, dans le cas où des opérateurs sont inclus dans le lambda, traitez la collection d'opérandes rendus avec le code SQL équivalent pour répondre aux exigences de l'opérateur.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi