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 lambda hypothétique:

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

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 le problème?

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

Exemples susceptibles de créer ce scénario:

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

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 constituerait une forme médiocre de ma part.

Était-ce utile?

La solution

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:

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

Les cas particuliers que vous devez gérer sont les suivants:

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

Ceux-ci sont représentés différemment dans l'arbre des expressions (sous la forme MemberExpression ). Donc, vous auriez besoin de mettre en cas spécial le 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 UnaryExpression dans le deuxième exemple):

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

Sinon, vous pourrez peut-être prétraiter l'arbre d'expression et traduire tous les cas particuliers dans leur forme canonique (arbre d'expression). Par exemple, tous les nœuds MemberExpression qui correspondent aux critères peuvent être transformés en BinaryExpression approprié.

Autres conseils

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

Ie. Évaluez chacun des éléments suivants:

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

à

WHERE (Enabled = 1)

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top