2012-03-20 97 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和ORs? Expression.And和Expression.Or的API只接受一個左右標準,而不是一個鏈。

有沒有人知道我在哪裏可以找到一個這樣的例子?

順便說一句,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 2012-03-21 08:07:19

+0

最後,我沒有嘗試這個,因爲我最初的嘗試實際上工作,我不想改變它。但我會將其標記爲答案,因爲它看起來像一個優雅的解決方案(我希望它也可以)。我會分開發布我的答案。 – joniba 2012-03-21 09:32:42

1

隨着標準的API,你可以使用連詞(AND)和析取(OR)班。舉例來說,請參閱this stackoverflow thread

+0

因此,在Conjunction()之後,您可以添加儘可能多的限制/表達式,並且它們將通過add/or?還是我不明白這個例子? – joniba 2012-03-21 08:14:41

+0

基本上是。連接採用數字限制,並將它們與邏輯AND進行鏈接。分離也需要一些限制,但用OR來鏈接它們。你也可以在連詞中包含一個析取關係,反之亦然。 – 2012-03-21 09:30:35

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是完全一樣的,我想。