c# - 从 IQueryable<T> 中删除 OrderBy

标签 c# .net linq linq-to-sql iqueryable

我有一个分页 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 Server 之前对其进行操作。

我的问题是,如果我已经有一个带有 OrderBy 的 IQueryable,是否可以在调用 Count() 之前删除该 OrderBy?

比如:totalRecordCount = queryable.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/

相关文章:

c# - Notifyicon 气球提示未在 C# 中显示?

javascript - TypeScript运行时错误 'undefined'

c# - 如何将基类型列表转换为派生类型列表

c# - 通过动态创建 linq 查询在 c# 中为 Sql 等效项 "column is null"创建 Linq 表达式

c# - Linq 是否根据实际集合类型优化执行?

c# - 不能 "Add or Update"实体,因为无法更改主键

javascript - 在 Web 方法中获取 JSON 数组中的数组?如何?

c# - 如何使用 C# 将数据从我的 API 传输到 Dynamic 365 API

c# - 如何模拟C#线程饥饿

c# - 在 C# 中使用 SSH.NET SFTP 下载目录