0

SQL 文字列を生成するライブラリを VB.NET で作成しています。WHEREただし、句(および同様の構造)を生成すると、問題が発生します。最も単純なwhere句の構造は本質的に

expression1 [AND expression2 [AND expressionN]]

これは、オブジェクトのリストを使用してコードで簡単に表現できます。プログラムは、それぞれをループし、オーバーライドされたメソッドをExpression呼び出して、毎回追加する必要があります (最後を除く)。単純。を考慮すると複雑になります。 where 句の構造は次のようになります。ToString()ANDOR

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 行のコレクション トリックであるか、まったく新しいクラスのファミリであるかは問題ではありません。保守性と拡張性は重要です。ハックであってはなりません。この種の問題を解決するデザイン パターンを誰かが知っている場合は、非常に興味があります。


編集: 要求に応じて、いくつかのサンプルコードを使用して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)
4

2 に答える 2

0

バロカルバスのソリューションに対する私自身のバリエーションは、ブール値を介してネストをより適切に制御できIsNested、2 つのコレクションの順序付けに依存しません。

Public Class ExpressionFromChainOfExpressions
    Inherits Expression

    Private ExprChain As List(Of Expression)

    'Alternatively use an Enum as per varocarbas's solution 
    'for better consistency control
    Private ChainWord As String

    'If true, wraps ( ) around ToString()'s output
    Private IsNested As Boolean

    Public Sub New(ByVal ChainWord As String, ByVal IsNested As Boolean)
        Me.ChainWord = ChainWord
        Me.IsNested = IsNested
    End Sub

    Public Sub AddExpression(ByVal Expr As Expression)
        If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
        ExprChain.Add(Expr)
    End Sub

    Public Overrides Function ToString() As String
        Dim outStr As String = ""
        If IsNested Then outStr = "("

        For i = 0 To ExprChain.Count - 1
            outStr &= ExprChain(i).ToString()
            If i < ExprChain.Count - 1 Then
                outStr &= String.Format(" {0} ", ChainWord)
            End If
        Next

        If IsNested Then outStr = ")"

        Return outStr
    End Function
End Class

などの複雑な出力が可能

expr1 AND expr2 OR (exp3 AND (expr4 OR expr5 AND expr6 AND expr7))
于 2013-08-23T11:40:52.887 に答える