score:2

Accepted answer

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.


Related Articles