我有一个分页 API,它返回用户请求的行,但一次只能返回这么多行,而不是整个集合。 API 按设计工作,但我必须计算可用的记录总数(用于正确的页面计算)。在 API 中,我使用了 Linq2Sql,并且在我最终提出请求之前,我经常使用 IQueryable。当我去获取计数时,我会调用类似的东西: totalRecordCount = queryable.Count();
结果 SQL 仍然很有趣,但它也添加了一个不必要的 Order By,这使得查询非常昂贵。
exec sp_executesql N'SELECT COUNT(*) AS [value]
FROM (
SELECT TOP (1) NULL AS [EMPTY]
FROM [dbo].[JournalEventsView] AS [t0]
WHERE [t0].[DataOwnerID] = @p0
ORDER BY [t0].[DataTimeStamp] DESC
) AS [t1]',N'@p0 int',@p0=1
因为我使用的是 IQueryable,所以我可以在 IQueryable 进入 SQL 服务器之前对其进行操作。
我的问题是,如果我已经有一个带有 OrderBy 的 IQueryable,是否可以在调用 Count() 之前删除该 OrderBy?
像:totalRecordCount = 可查询。 NoOrder .Count();
如果没有,没什么大不了的。我看到很多关于如何 OrderBy 的问题,但没有任何涉及从 Linq 表达式中删除 OrderBy 的问题。
谢谢!
最佳答案
所以,下面的代码是针对内存数组的一个尖峰。使用 Entity Framework (或其他一些任意的 IQueryProvider 实现)可能会遇到一些障碍。基本上,我们要做的是访问表达式树并查找任何 Ordering 方法调用并将其从树中删除。希望这为您指明了正确的方向。
class Program
{
static void Main(string[] args)
{
var seq = new[] { 1, 3, 5, 7, 9, 2, 4, 6, 8 };
var query = seq.OrderBy(x => x);
Console.WriteLine("Print out in reverse order.");
foreach (var item in query)
{
Console.WriteLine(item);
}
Console.WriteLine("Prints out in original order");
var queryExpression = seq.AsQueryable().OrderBy(x => x).ThenByDescending(x => x).Expression;
var queryDelegate = Expression.Lambda<Func<IEnumerable<int>>>(new OrderByRemover().Visit(queryExpression)).Compile();
foreach (var item in queryDelegate())
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
public class OrderByRemover : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType != typeof(Enumerable) && node.Method.DeclaringType != typeof(Queryable))
return base.VisitMethodCall(node);
if (node.Method.Name != "OrderBy" && node.Method.Name != "OrderByDescending" && node.Method.Name != "ThenBy" && node.Method.Name != "ThenByDescending")
return base.VisitMethodCall(node);
//eliminate the method call from the expression tree by returning the object of the call.
return base.Visit(node.Arguments[0]);
}
}
关于c# - 从 IQueryable<T> 中删除 OrderBy,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10591010/