I am trying to implement a LINQ Expression Visitor ([ExpressionVisitor][1]
) for the following scenario: remove all pagination-related calls, such as Skip
, Take
, OrderBy
, and OrderByDescending
.
What I came up so far was this:
public class RemovePaginationExpressionVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == nameof(Enumerable.Skip) || node.Method.Name == nameof(Enumerable.Take) || node.Method.Name == nameof(Enumerable.OrderBy) || node.Method.Name == nameof(Enumerable.OrderByDescending))
{
return Expression.Constant(true);
}
return base.VisitMethodCall(node);
}
}
Here's how I use it:
var query = ctx.MyEntities.Where(x => x.Status == Status.Active).Skip(5).Take(10).OrderBy(x => x.Name);
var interceptor = new RemovePaginationExpressionVisitor();
var expression = interceptor.Visit(query.Expression);
This kind of works, meaning, it does get rid of these calls, but, it also removes any other conditions that I may have, like, in this case, Where(x => x.Status == Status.Active)
.
So, two questions:
I ended up implementing like this:
public class RemovePaginationExpressionVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType == typeof(Queryable) &&
(node.Method.Name == nameof(Queryable.Take) ||
node.Method.Name == nameof(Queryable.Skip) ||
node.Method.Name == nameof(Queryable.OrderBy) ||
node.Method.Name == nameof(Queryable.OrderByDescending) ||
node.Method.Name == nameof(Queryable.ThenBy) ||
node.Method.Name == nameof(Queryable.ThenByDescending)))
{
return Visit(node.Arguments[0]);
}
return base.VisitMethodCall(node);
}
}
And using it as this:
var expression = interceptor.Visit(query.Expression);
var modifiedQuery = query.Provider.CreateQuery<MyEntity>(expression);
And it works like a charm! Beware, however, because it will remove all "paging" method calls, which may or may not be what you want. You may need to add a condition to check if it's at the "external" level, not in some inner query.