如何知道OrderBy是否应用于查询?

我需要知道在应用.Skip或.Take之前是否将OrderBy应用于Linq查询。 我无法控制收到的查询,如果应用了OrderBy,我需要维护这个,在任何其他情况下我应该OrderBy(t => true)。 我尝试过以下方法:

DataContext db; var query = db.Orders; var wasOrderByApplied = typeof(IOrderedQueryable).IsAssignableFrom(query.AsQueryable().Expression.Type); var wasOrderByApplied2 = query.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery); var wasOrderByApplied3 = typeof(IOrderedQueryable) == query.AsQueryable().Expression.Type; var query2 = db.Orders.OrderBy(o => o.CreationDate); var wasOrderByApplied4 = typeof(IOrderedQueryable).IsAssignableFrom(query2.AsQueryable().Expression.Type); var wasOrderByApplied5 = query2.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery); var wasOrderByApplied6 = typeof(IOrderedQueryable) == query2.AsQueryable().Expression.Type; var query3 = db.Orders.OrderBy(o => o.CreationDate).Where(o => o.Id > 4); var wasOrderByApplied7 = typeof(IOrderedQueryable).IsAssignableFrom(query3.AsQueryable().Expression.Type); var wasOrderByApplied8 = query3.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery); var wasOrderByApplied9 = typeof(IOrderedQueryable) == query3.AsQueryable().Expression.Type; 

结果在哪里:

 wasOrderByApplied = true; wasOrderByApplied2 = true; wasOrderByApplied3 = false; wasOrderByApplied4 = true; wasOrderByApplied5 = false; wasOrderByApplied6 = true; 

对于最后的结果,似乎第三个问题询问每个查询是正确的,但后来我做了第三个查询(query3)和结果,其中:

 wasOrderByApplied7 = false; wasOrderByApplied8 = false; wasOrderByApplied9 = false; 

当我在OrderBy之后添加一个Where时,问题结果为false ,它应该是真的

有没有更好的方法来了解OrderBy是否应用于查询?

这是我想到的一种可能的解决方案:

创建一个表达式访问者,检查表达式是否调用OrderBy ,或者调用OrderByDescending方法,如下所示:

 public class MyVisitor : ExpressionVisitor { public bool HasOrderBy { get; private set; } protected override Expression VisitMethodCall(MethodCallExpression node) { if (node.Method.DeclaringType == typeof (Queryable) && (node.Method.Name == "OrderBy" || node.Method.Name == "OrderByDescending")) HasOrderBy = true; return base.VisitMethodCall(node); } } 

以下是如何使用它:

 MyVisitor visitor = new MyVisitor(); visitor.Visit(query.Expression); if (visitor.HasOrderBy) { //.. } else { //.. } 

你不需要知道什么。 这毫无意义。 如果你想TakeSkip一些元素,你需要在它之前订购它们。 考虑以下

 class Animal { public int Weight { get; set; } public int NumberOfLegs { get; set; } } ... public IEnumerable TakeFive(IEnumerable animals) { return animals.Take(5); } 

你会带五个动物? 什么腿最多? 还是那些更重的? 还是那些重量较轻的? 你不知道。 但是如果你改变这样的代码

 public IEnumerable TakeFive(IEnumerable animals) { return animals.OrderBy(_ => .Weight).Take(5); } 

它开始有道理了。

您不仅可以将其应用于IEnumerable ,还可以应用于IQueryable 。 如果您不知道订单是什么,则无需知道序列是否已订购。