2012-03-20 8 views
0

私はこれに似た(または同等の効果を持つ)SQL結果となる基準クエリを作成する方法の例を探していた:NHibernateの基準クエリ - どのようにチェーンの論理演算子

SELECT x, y, z 
FROM SomeTable tbl 
WHERE tbl.a = 'some value' 
    AND (
    (tbl.b = '1' AND tbl.c = 'whatever1' AND tbl.d = 123) OR 
    (tbl.b = '2' AND tbl.c = 'whatever2' AND tbl.d = 456) OR 
    (tbl.b = '3' AND tbl.c = 'whatever3' AND tbl.d = 789) 
) 

作成する場合クエリ私はフィルタデータのリスト( "AND"の後に来るデータを埋める)と余分なパラメータ(上記の 'いくつかの値'部分を埋める)を持っています。

基本的に私の質問は、この種の基準クエリを作成するときにANDとORをどのようにチェーン化するのですか? Expression.AndとExpression.OrのAPIは、チェーンではなく左右の1つの基準のみを受け入れます。

私はこれについての例をどこに見つけることができますか?

ところで、x、y、zの部分(SELECTの後)は、現在のところプロジェクションでは達成できないようです(まだ取得していないようです)。

答えて

1

論理演算子の連鎖はありません。上記は、次のように書くこともできます。

(tbl.b = '1' AND tbl.c = 'whatever1' AND tbl.d = 123) OR 
    ((tbl.b = '2' AND tbl.c = 'whatever2' AND tbl.d = 456) OR 
    (tbl.b = '3' AND tbl.c = 'whatever3' AND tbl.d = 789)) 

つまり、論理演算子は常に左と右のパラメータを持ちます。ビット演算子がRestrictionオーバーロードされている、と述べた

ので、次のような作品:

criteria.Add(Restrictions.Eq("a", "some value") & 
      (Restrictions.Eq("b", 1) & Restrictions.Eq("c", "whatever1") | 
      (Restrictions.Eq("b", 2) & Restrictions.Eq("c", "whatever2")))) 
      //...etc... 
+0

これは素晴らしいですね!私はそれを試してみる... – joniba

+0

実際に私の最初の試みが実際に働いたので、私はこれを試していなかったし、私はそれを変更する気がしない。しかし、私はこれを答えとしてマークします。なぜなら、それは優雅な解決策のように思えるからです。私は答えを別に掲示します。 – joniba

1

あなたは接続詞(AND)を使用して、論理和(OR)のクラスできる基準APIを使用しました。例については、this stackoverflow thread

+0

Conjunction()の後に、好きなだけ多くの制限/式を追加することができ、add/or?によって結合されます。あるいは私はその事例を理解していませんか? – joniba

+0

基本的にはyesです。結合詞は数の制限を受け、それらを論理ANDで連結します。また、Disjunctionはいくつかの制限を受けますが、それらをORで連結します。また、結合に結合を含めることもできます(逆も同様です)。 –

0

実際には私の最初の試みが実際に働いたように見えるので、誰かに興味がある場合にどのようにしたのかを投稿します。

public IEnumerable<Entity> Filter(FilterRequest filterRequest) 
    { 
     var criteria = session.CreateCriteria("Entity"); 

     criteria.Add(
      Expression.And(
       CreateItemCriteria(filterRequest), 
       CreateKeysCriteria(filterRequest))); 

     return criteria.List<Entity>(); 
    } 

    private static ICriterion CreateItemCriteria(FilterRequest filterRequest) 
    { 
     return Restrictions.Eq("a", filterRequest.ItemId); 
    } 

    private ICriterion CreateKeysCriteria(FilterRequest filterRequest) 
    { 
     ICriterion finalCriterion = null; 

     for (int i = 0; i < filterRequest.Keys.Count; i++) 
     { 
      var currentKeyCriterion = CreateKeyCriterion(filterRequest.Keys[i]); 

      finalCriterion = finalCriterion == null 
       ? currentKeyCriterion 
       : Expression.Or(finalCriterion, currentKeyCriterion); 
     } 

     return finalCriterion; 
    } 

    private ICriterion CreateKeyCriterion(Key key) 
    { 
     return Expression.AllEq(new Dictionary<string, object> 
      { 
       { "b", Key.b }, 
       { "c", Key.c }, 
       { "d", Key.d }, 
      }); 
    } 

ひどくエレガントな、それが動作し、結果のSQLは、私が望んでいたとおりにされていない:それは次のようになります。