我正在 VB.NET 中创建一个生成 SQL 字符串的库。然而,生成WHERE
子句(和类似的结构)给我带来了问题。我已经确定最简单的 where 子句结构本质上是
expression1 [AND expression2 [AND expressionN]]
这很容易用Expression
对象列表在代码中表示 - 然后程序只需遍历每个对象,调用其覆盖的方法并每次ToString()
附加(最后一个除外)。AND
简单的。当OR
考虑到复杂性时: where 子句的结构变成
expression1 [[AND|OR] expression2 [[AND|OR] expressionN]]
我现在需要既能保存所有的表达式,又能跟踪每个表达式是否与下一个分隔为AND
or OR
- 一个本质上的集合(expr1, andOr1, expr2, andOr2, ... exprN, andOrN)
我还考虑过结构也可以嵌套,例如:
(expression1 [[AND|OR] expression2]) [AND|OR] (expression3 [[AND|OR] expression4])
每个带圆括号的一半本身就是一个表达式。所以我认为解决方案是通过Expression
进一步扩展类来实现,这样一个表达式可以是一个表达式链:我有一个新类ExpressionFromChainOfExpressions
:
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
Public Sub AddExpression(Expr As Expression)
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expression)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = "("
For i = 0 To ExprChain.Count - 1
outStr &= Expr.ToString()
If i < ExprChain.Count - 1
'ToDo: Determine [AND|OR] and append
'OLD: outStr &= " AND "
End If
Next
Return outStr & ")"
End Function
End Class
And
将/Or
作为布尔标志或类似的东西捆绑到Expression
类中感觉是错误的 -Expression
应该可以在其他地方重用(它们也出现在其他情况下,例如case when expression [[and|or] expression] ...
, 并且And
/Or
本身不是表达式的一部分。
解决方案是 3 行集合技巧还是全新的类家族都没有关系。可维护性和可扩展性很重要——它不能是一个hack。如果有人知道解决此类问题的设计模式,我会非常有兴趣看到它。
编辑:根据要求,一些示例代码只是使用And
(由于实际移动部件的数量,从实际代码中大大简化了):
Public MustInherit Class Expression
Public MustOverride Function ToString() As String
End Class
Public Class ExpressionFromString
Inherits Expression
Private ExprString As String
Public Sub New(ExprString As String)
Me.ExprString = ExprString
End Sub
Public Overrides Function ToString() As String
Return ExprString
End Function
End Class
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
Public Sub AddExpression(Expr As Expression)
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expression)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = "("
For i = 0 To ExprChain.Count - 1
outStr &= Expr.ToString()
If i < ExprChain.Count - 1
outStr &= " AND "
End If
Next
Return outStr & ")"
End Function
End Class
主要方法:
Public Module Module1
Dim myExpr1 = New ExpressionFromString("A = B")
Dim myExpr2 = New ExpressionFromString("C > 100")
dIM myExpr3 = New ExpressionFromString("D Is Null")
Dim myNestedChain = New ExpressionFromChainOfExpressions()
myExprChain.Add(myExpr1)
myExprChain.Add(myExpr2)
Console.WriteLine("WHERE " & myNestedChain.ToString() )
Dim myOuterChain = New ExpressionFromChainOfExpressions()
myOuterChain.Add(myNestedChain)
myOuterChain.Add(myExpr3)
Console.WriteLine("WHERE " & myOuterChain.ToString() )
End Module
输出:
WHERE (A = B AND C > 100)
WHERE ((A = B AND C > 100) AND D Is Null)