Reputation: 1461
Having different kind of filter following used in different situation. How to apply more than 1 filter in a 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
Upvotes: 0
Views: 4373
Reputation:
It depends on the type of dataList
.
If it's IEnumerable<data>
, then you can use functions instead of expressions, and a lambda function for the Where clause:
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));
However if the type is IQueryable<data>
, then you will need to use multiple calls to the Queryable version of Where:
var all = dataList.Where(filter1).Where(filter2).Where(filter3);
var any = dataList.Where(filter1)
.Union(dataList.Where(filter2))
.Union(dataList.Where(filter3))
.Distinct();
Upvotes: 2
Reputation: 963
Best practies,
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();
Upvotes: 0
Reputation: 249706
If you want to combine the conditions using and you can just use several where operators:
// equivalent to filter1 && filter2 && filter3
var result = dataList.Where(filter1).Where(filter2).Where(filter3);
If you want to combine the filters using or it is a bit more complicated, you need to manually manipulate the expressions, I have this small util that can do that:
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);
}
}
Usage:
// equivalent to filter1|| filter2 || filter3
var result4 = dataList.Where(CombineWithOr(filter1, filter2, filter3));
Upvotes: 0
Reputation: 3919
You can simply call .Where(filter)
for every filter that you want to apply.
You can filter the IEnumerable<T>
that .Where()
returns again, filtering out all elements that you want.
Usage:
IEnumerable<someType> result = dataList.Where(filter1).Where(filter2).Where(filter3);
What you could do aswell is have all the filtering conditions in a single expression, instead of multiple ones.
Upvotes: 2