NHibernate标准查询 - 如何链接逻辑运算符

时间:2012-03-20 17:30:14

标签: nhibernate nhibernate-criteria

我正在寻找一个如何创建条件查询的示例,该查询会导致SQL与此类似(或具有等效效果):

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只接受单个左右标准,而不是链。

有谁知道我可以在哪里找到一个例子?

顺便说一下,x,y,z部分(在SELECT之后)目前无关紧要,因为我似乎可以用投影来完成它(还没有到达那里)。

3 个答案:

答案 0 :(得分: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...

答案 1 :(得分:1)

使用条件API,您可以使用连词(AND)和Disjunction(OR)类。有关示例,请参阅this stackoverflow thread

答案 2 :(得分: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完全符合我的要求。