如何计算 LINQ 表达式树中的独立布尔表达式
我使用标准访问者模式来迭代 LINQ 表达式树,以生成动态 SQL WHERE 子句。
我的问题是,与 C# 不同,您不能在 SQL 中使用独立的布尔表达式;你必须将它与 1 或 0 进行比较。
给定这个假设的 lambda 表达式:
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
当然,最后一个示例的风格很差,但我的代码被设计为可以工作独立于程序员的技能水平,因此不满足冗余场景对我来说是一种糟糕的形式。
I'm using the standard visitor pattern to iterate through a LINQ expression tree in order to generate dynamic SQL WHERE clauses.
My issue is that unlike C#, you can't use a standalone boolean expression in SQL; you have to compare it to either 1 or 0.
Given this hypothetical lambda expression:
h => h.Enabled || h.Enabled == false
It would be easy to mistakenly generate this code:
WHERE Enabled OR Enabled = 0
or this code:
WHERE (Enabled = 1) OR (Enabled = 1) = 0
Both of course will generate an SQL error. What logic should I apply to get around this without my code starting to look really obtuse as I delve deep into subtrees to figure out what the case may be?
EDIT: The example above is of course redundant - I am only using it to illustrate a point.
Examples that could create this scenario:
h => h.Enabled
h => h.Enabled == enabled
h => h.Enabled == true
Naturally that last example is poor style, but my code is being designed to work independent of the programmer's skill level, so to not cater for redundant scenarios would be poor form on my part.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下情况非常简单:
这些是
BinaryExpression
节点,您可以直接将它们转换为:您需要处理的特殊情况是:
这些在表达式树中以不同的方式表示(作为
MemberExpression
)。因此,您需要对MemberExpression
进行特殊处理,并确定它是否正在访问布尔属性。如果是,则将其转换为规范形式(检测第二个示例中的 UnaryExpression ):或者,您可以预处理表达式树并将任何特殊情况转换为其规范形式(表达式树)形式。例如,任何符合条件的
MemberExpression
节点都可以转换为正确的BinaryExpression
。The following cases are pretty straight forward:
These are
BinaryExpression
nodes, and you can directly translate them into:The special case(s) that you need to handle are:
Those are represented differently in the expression tree (as a
MemberExpression
). So you would need to special case theMemberExpression
and determine if it's accessing a boolean property or not. If it is, then you translate it into the canonical form (detecting theUnaryExpression
in the second example):Alternatively, you might be able to pre-process the expression tree and translate any special cases into their canonical (expression tree) form. For example, any
MemberExpression
nodes that fit the criteria could be transformed into the correctBinaryExpression
.在评估运算符之前是否无法完全处理操作数?
IE。 Eval every:
to ,
然后在 lambda 中包含运算符的情况下,使用等效的 SQL 处理呈现的操作数集合以满足运算符要求。
Is it not possible to process the operands completely before eveluating the operators?
Ie. Eval each of:
to
and then in the case where operators are included in the lambda, process the collection of rendered operands with the equivalent SQL to meet the operator requirements.
其他人可能有同样的问题。我通过将最后一个
BinaryExpression
保存到变量中解决了这个问题这将解决以下不同的布尔子句
This处理独立布尔值的代码
不在此变量下
BinaryExpression prviousBinaryExp = null;
当您点击
BinaryExpression
时,然后将该表达式保存在上面的变量中这是检查先前表达式是否为二进制表达式以及当前表达式是否为
BinaryExpression
的一部分的逻辑Left
或Right
表达式。我们将检查Nodtype
,它不应该是ExpressionType.Equal
和ExpressionType.NotEqual
(f.IsActive == true)。我们还将确保如果BinaryExpression
的Left
和Right
是UnaryExpression
,那么我们将检查它的UnaryExpression.Operand
等于当前表达式。这将处理 !f.Enabled 或 !f.IsActive 等。最后,我将表达式转换为 OData 等效字符串。这是
Other may have same question. I have solved this by saving last
BinaryExpression
into a variableThis will solve the following different boolean clauses
This the code which handles standalone boolean
Not down this variable
BinaryExpression prviousBinaryExp = null;
When you hit
BinaryExpression
then save that expression in above variableThis is the logic which checks if a previous expression was binaryexpression and the the current expression is the part of the
BinaryExpression's
Left
orRight
expression. We will check theNodtype
which should not beExpressionType.Equal
andExpressionType.NotEqual
(f.IsActive == true). We will also make sure that ifLeft
andRight
ofBinaryExpression
isUnaryExpression
than we will check it'sUnaryExpression.Operand
is equal to current expression. This will handled !f.Enabled or !f.IsActive etc.Finally I am converting Expression to OData equivalent string. Which is