【问题标题】:NHibernate criteria queries - How to chain logical operatorsNHibernate 条件查询 - 如何链接逻辑运算符
【发布时间】:2012-03-20 17:30:14
【问题描述】:

我正在寻找一个示例,说明如何创建一个条件查询,该查询将产生与此类似的 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 之后)目前无关紧要,因为我似乎可以通过投影来完成它(还没有到达那里)。

【问题讨论】:

    标签: nhibernate nhibernate-criteria


    【解决方案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...
    

    【讨论】:

    • 最后我没有尝试这个,因为我最初的尝试确实有效,我不想改变它。但我会将其标记为答案,因为它似乎是一个优雅的解决方案(我希望它也能工作)。我将单独发布我的答案。
    【解决方案2】:

    通过条件 API,您可以使用合取 (AND) 和析取 (OR) 类。示例见this stackoverflow thread

    【讨论】:

    • 所以在 Conjunction() 之后,您可以添加任意数量的限制/表达式,它们将通过添加 / 或?还是我没看懂这个例子?
    • 基本上是的。连词接受一个数字限制,并用逻辑 AND 将它们链接起来。 Disjunction 也有许多限制,但用 OR 将它们链接起来。您还可以在连词中包含析取,反之亦然。
    【解决方案3】:

    好吧,看来我最初的尝试确实奏效了,所以我会发布我是如何做到的,以防万一有人感兴趣。它看起来像这样:

        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 正是我想要的。

    【讨论】:

      猜你喜欢
      • 2021-08-16
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多