【问题标题】:Combine expressions for Where statement [duplicate]组合 Where 语句的表达式 [重复]
【发布时间】:2012-05-07 16:37:23
【问题描述】:

可能重复:
How do I combine LINQ expressions into one?

public bool IsUnique(params Expression<Func<Employee, bool>>[] properties)
{
    var combinedProperties = Combine(properties);
    var rowCount = _session.QueryOver<Employee>().Where(combinedProperties).ToRowCountQuery().RowCount();
    return rowCount == 0;
}

Expression<Func<Employee, bool>> Combine(Expression<Func<Employee, bool>>[] properties)
{
    ???
}

用法:

var isUnique = _employeeRepository.IsUnique(x => x.FirstName == commandMessage.FirstName, x => x.LastName == commandMessage.LastName);

有没有一种方法可以将谓词与 AND 运算符结合起来?

【问题讨论】:

    标签: c# linq lambda expression expression-trees


    【解决方案1】:

    最简单的方法是遍历您的 params 数组并为每个表达式调用 .Where。

    Pseudo
    var query = _session.QueryOver<Employee>()
    for each expression in expressions
       query = query.Where(expression)
    

    我知道这不是您所问的,但它可能已经足够好,因为它实现了总体目标?

    【讨论】:

      【解决方案2】:

      我认为扩展方法会更有用,并且适用于所有 IEnumerable 查询:

      public static class MyExtensions
      {
          // usage:
          // myList.CombinedWhere(x => x.Name == "John", x => x.City == "Miami", x => x.Code > 5);
          public static IEnumerable<T> CombinedWhere<T>(this IEnumerable<T> source,
              params Func<T, bool>[] predicates)
          {
              var query = source.Where(l => true);
              foreach(var pred in predicates)
              {
                  query = query.Where (pred);
              }
              return query;
          }
      }
      

      就像使用 Where 扩展一样使用它,除了可以使用可变数量的参数。

      添加上述扩展后,您的代码略有变化:

      public bool IsUnique(params Func<Employee, bool>[] predicates)
      {
          var rowCount = _session.QueryOver<Employee>()
                   .CombinedWhere(predicates).ToRowCountQuery().RowCount();
          return rowCount == 0;
      }
      
      var isUnique = _employeeRepository.IsUnique(
                   x => x.FirstName == commandMessage.FirstName,
                   x => x.LastName == commandMessage.LastName);
      

      其实,现在我看了,你或许可以把它归结为一个表达式:

      var isUnique = (_session.QueryOver<Employee>()
         .CombinedWhere( 
              x => x.FirstName == commandMessage.FirstName, 
              x => x.LastName == commandMessage.LastName)
         .ToRowCountQuery()
         .RowCount()) == 0; // == 1?
      

      【讨论】:

        【解决方案3】:

        是的,您可以将 LinqKit 与 .Invoke() 一起使用

        Expression<Func<Purchase,bool>> criteria1 = p => p.Price > 1000;
        Expression<Func<Purchase,bool>> criteria2 = p => criteria1.Invoke (p)
                                                         || p.Description.Contains ("a");
        

        【讨论】:

          【解决方案4】:

          感谢 Brad Rem 和 Kenneth Ito,他们给了我一些灵感。

          这是适用于 NHibernate 的 IQueryOver API 的解决方案。

          存储库:

          public bool IsUnique(int id, params Expression<Func<T, bool>>[] properties)
          {
              var rowCount = _session.QueryOver<T>().CombinedWhere(properties).ToRowCountQuery().RowCount();
              // create
              if (id == 0)
              {
                  return rowCount == 0;
              }
              // update
              return rowCount <= 1;
          }
          

          IQueryOver 扩展:

          public static class IQueryOverExtension
          {
              public static IQueryOver<T, T> CombinedWhere<T>(this IQueryOver<T, T> source, params Expression<Func<T, bool>>[] predicates)
              {
                  return predicates.Aggregate(source, (current, predicate) => current.Where(predicate));
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-23
            • 1970-01-01
            • 2022-01-05
            • 1970-01-01
            • 2018-01-25
            相关资源
            最近更新 更多