Как оценить автономное логическое выражение в дереве выражений LINQ - PullRequest
2 голосов
/ 15 сентября 2009

Я использую стандартный шаблон посетителя для итерации по дереву выражений LINQ с целью создания динамических предложений SQL WHERE.

Моя проблема в том, что в отличие от C #, вы не можете использовать автономное логическое выражение в SQL; Вы должны сравнить его с 1 или 0.

Учитывая это гипотетическое лямбда-выражение:

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

Было бы легко по ошибке сгенерировать этот код:

WHERE Enabled OR Enabled = 0

или этот код:

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

Оба, конечно, сгенерируют ошибку SQL. Какую логику я должен применить, чтобы обойти это без того, чтобы мой код не выглядел действительно тупым, когда я углубляюсь в поддеревья, чтобы выяснить, в чем дело?

РЕДАКТИРОВАТЬ: приведенный выше пример, конечно, излишним - я использую его только для иллюстрации точки.

Примеры, которые могут создать этот сценарий:

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

Естественно, что последний пример - плохой стиль, но мой код предназначен для работы независимо от уровня навыка программиста, поэтому не удовлетворять избыточным сценариям будет плохо с моей стороны.

Ответы [ 2 ]

5 голосов
/ 23 ноября 2009

Следующие случаи довольно просты:

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

Это BinaryExpression узлы, и вы можете напрямую перевести их в:

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

Особый случай (ы), который вам нужно обработать:

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

Они представлены по-разному в дереве выражений (как MemberExpression). Таким образом, вам необходимо выполнить специальный случай MemberExpression и определить, имеет ли он доступ к логическому свойству или нет. Если это так, то вы переводите его в каноническую форму (обнаружив UnaryExpression во втором примере):

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

Кроме того, вы можете предварительно обработать дерево выражений и перевести любые особые случаи в их каноническую (дерево выражений) форму. Например, любые MemberExpression узлы, которые соответствуют критериям, могут быть преобразованы в правильные BinaryExpression.

0 голосов
/ 23 ноября 2009

Разве невозможно полностью обработать операнды, прежде чем объяснить операторов?

Т.е.. Оцените каждый из:

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

до

WHERE (Enabled = 1)

, а затем в случае, когда операторы включены в лямбду, обрабатывают коллекцию визуализированных операндов с эквивалентным SQL для удовлетворения требований оператора.

...