質問

標準の訪問者パターンを使用して、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

当然、最後の例は貧弱なスタイルですが、私のコードはプログラマーのスキルレベルに依存せずに動作するように設計されているため、冗長なシナリオに対応しないことは私にとっては貧弱な形です。

役に立ちましたか?

解決

次のケースは非常に単純です:

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

これらは BinaryExpression ノードであり、これらを直接翻訳できます:

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

処理する必要がある特殊なケースは次のとおりです。

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

これらは、式ツリーで( MemberExpression として)異なって表されます。そのため、 MemberExpression を特殊なケースにして、ブールプロパティにアクセスしているかどうかを判断する必要があります。そうである場合は、正規形式に変換します(2番目の例の UnaryExpression を検出します):

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

別の方法として、式ツリーを前処理して、特殊なケースを正規の(式ツリー)形式に変換できる場合があります。たとえば、基準に適合する MemberExpression ノードは、正しい BinaryExpression に変換できます。

他のヒント

演算子を検証する前にオペランドを完全に処理することはできませんか?

つまり。それぞれの評価:

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

to

WHERE (Enabled = 1)

そして、演算子がラムダに含まれる場合、演算子の要件を満たすために、同等のSQLでレンダリングされたオペランドのコレクションを処理します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top