2

可能重复:
如何将 LINQ 表达式组合为一个?

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

4 回答 4

5

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

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

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

于 2012-05-07T17:16:16.360 回答
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?
于 2012-05-07T19:43:45.300 回答
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));
    }
}
于 2012-05-08T08:53:06.773 回答
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");
于 2012-05-07T16:41:21.560 回答