Reputation: 327
I need to add an "Or" clause in a where clause dynamically, depending on some conditions to an existing IQueryable object.
Using ExpressionBuilder, I can compose a left and right Expression> but for that to wrok, I need to extract the Expression> from my IQueryable instance. Is it possible?
Sample code:
var list = _context.Set<T>().Where(x=>x.Id == 1);
if(someValue)
{
var leftExpression = list.???? //I would extract the Expression<Func<T, bool>> here
var orExpression = (T x) => x.Status == 1;
var newWhereClause = ExpressionBuilder.Or(leftExpression, orExpression);
list = list.Where(newWhereClause);
}
The ExpressionBuilder code was taken from this link: https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/
Thanks!
Upvotes: 1
Views: 1381
Reputation: 26917
What you have to do is break down the original IQueryable
, extract the source and query expression and then build a new query expression and then a new IQueryable from the source and the new query expression. If there is no Where
, just add the condition to the original query.
IQueryable<T> q = _context.Set<T>().Where(x => x.Id == 1);
if(someValue) {
Expression<Func<T,bool>> newWhereClause = (T x) => x.Status == 1;
Expression source;
if (q.Expression is MethodCallExpression qe && qe.Method.Name == "Where") {
var we = (MethodCallExpression)q.Expression; // get the call to Where
var wea1 = (UnaryExpression)we.Arguments[1]; // get the 2nd arg to Where (Quoted Lambda)
var leftExpr = (Expression<Func<T, bool>>)wea1.Operand; // Extract the lambda from the QuoteExpression
newWhereClause = ExpressionBuilder.Or(leftExpr, newWhereClause);
q = q.Provider.CreateQuery<T>(we.Arguments[0]).Where(newWhereClause);
}
else
q = q.Where(newWhereClause);
}
Note that this depends on the internals of LINQ and expression trees, and could break at some point in the future.
Upvotes: 2