结合Where语句的表达式

时间:2012-05-07 16:37:24

标签: c# linq lambda expression expression-trees

  

可能重复:
  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运算符组合在一起?

4 个答案:

答案 0 :(得分:5)

最简单的方法是遍历你的params数组并调用。每个表达式都在这里。

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

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

答案 1 :(得分:1)

我认为扩展方法会更有用,并且可以处理所有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?

答案 2 :(得分:0)

是的,您可以将LinqKit与.Invoke()

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

答案 3 :(得分:0)

感谢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));
    }
}