2012-03-20 37 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是完全一样的,我想。