在linq中应用多个表达式

时间:2017-09-12 09:07:28

标签: c# linq

在不同的情况下使用不同类型的过滤器。如何在LinQ中应用多个过滤器。

Expression<Func<data, bool>> filter =
                    bt => bt.condition1 == condition1;
Expression<Func<data, bool>> filter2 =
                    bt => bt.condition2 == condition2;
Expression<Func<data, bool>> filter3 =
                    bt => bt.condition3 == condition3;


var result = dataList.Where(filter1);
var result2 = dataList.Where(filter2, filter3); //Syntax error
var result3 = dataList.Where(filter2).Where(filter3); //Is this proper?
var result4 = dataList.Where(filter2 || filter3); //Syntax error

4 个答案:

答案 0 :(得分:2)

您只需为要应用的每个过滤器调用.Where(filter)即可。

您可以过滤IEnumerable<T>再次返回的.Where(),过滤掉您想要的所有元素。

用法:

IEnumerable<someType> result = dataList.Where(filter1).Where(filter2).Where(filter3);

你可以做的是在单个表达式中具有所有过滤条件,而不是多个过滤条件。

答案 1 :(得分:0)

最佳实践,

var query = fooContext.User.AsQueryable();

if (condition1!= null)
    query = query.Where(x => x.condition1==condition1);
if (condition2 != null)
    query = query.Where(x => x.condition2== condition2 );

return await query.ToList();

答案 2 :(得分:0)

如果你想结合使用的条件,你可以使用几个运算符:

// equivalent to filter1 && filter2 && filter3
var result = dataList.Where(filter1).Where(filter2).Where(filter3); 

如果你想要使用过滤器或者它有点复杂,你需要手动操作表达式,我有这个小的工具,可以做到这一点:

public static Expression<Func<T, bool>> CombineWithOr<T>(params Expression<Func<T, bool>>[] filters)
{
    var first = filters.First();
    var param = first.Parameters.First();
    var body = first.Body;

    foreach(var other in filters.Skip(1))
    {
        var replacer = new ReplaceParameter
        {
            OriginalParameter = other.Parameters.First(),
            NewParameter = param
        };
        // We need to replace the original expression parameter with the result parameter
        body = Expression.Or(body, replacer.Visit(other.Body));
    }

    return Expression.Lambda<Func<T, bool>>(
        body,
        param
    );
}
class ReplaceParameter : ExpressionVisitor
{
    public Expression OriginalParameter { get; set; }
    public Expression NewParameter { get; set; }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        return node == this.OriginalParameter ? this.NewParameter : base.VisitParameter(node);
    }
}

用法:

// equivalent to filter1|| filter2 || filter3
var result4 = dataList.Where(CombineWithOr(filter1, filter2, filter3)); 

答案 3 :(得分:0)

这取决于dataList的类型。

如果它是IEnumerable<data>,那么你可以使用函数而不是表达式,以及Where子句的lambda函数:

Func<data, bool> filter =  (bt => bt.condition1 == condition1);
Func<data, bool> filter2 = (bt => bt.condition2 == condition2);
Func<data, bool> filter3 = (bt => bt.condition3 == condition3);

var all = dataList.Where(d => filter1(d) && filter2(d) && filter3(d));
var any = dataList.Where(d => filter1(d) || filter2(d) || filter3(d));

但是,如果类型为IQueryable<data>,则您需要对Where的可查询版本使用多次调用:

var all = dataList.Where(filter1).Where(filter2).Where(filter3);

var any = dataList.Where(filter1)
                  .Union(dataList.Where(filter2))
                  .Union(dataList.Where(filter3))
                  .Distinct();