我需要知道在应用.Skip或.Take之前是否将OrderBy应用于Linq查询。我无法控制收到的查询,如果应用了OrderBy,我需要维护这个,在任何其他情况下我应该OrderBy(t => true)。我尝试过以下方法:
DataContext db;
var query = db.Orders;
var wasOrderByApplied = typeof(IOrderedQueryable<Order>).IsAssignableFrom(query.AsQueryable().Expression.Type);
var wasOrderByApplied2 = query.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery<Order>);
var wasOrderByApplied3 = typeof(IOrderedQueryable<Order>) == query.AsQueryable().Expression.Type;
var query2 = db.Orders.OrderBy(o => o.CreationDate);
var wasOrderByApplied4 = typeof(IOrderedQueryable<Order>).IsAssignableFrom(query2.AsQueryable().Expression.Type);
var wasOrderByApplied5 = query2.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery<Order>);
var wasOrderByApplied6 = typeof(IOrderedQueryable<Order>) == query2.AsQueryable().Expression.Type;
var query3 = db.Orders.OrderBy(o => o.CreationDate).Where(o => o.Id > 4);
var wasOrderByApplied7 = typeof(IOrderedQueryable<Order>).IsAssignableFrom(query3.AsQueryable().Expression.Type);
var wasOrderByApplied8 = query3.AsQueryable().Expression.Type == typeof(System.Data.Entity.Core.Objects.ObjectQuery<Order>);
var wasOrderByApplied9 = typeof(IOrderedQueryable<Order>) == query3.AsQueryable().Expression.Type;
结果在哪里:
wasOrderByApplied = true;
wasOrderByApplied2 = true;
wasOrderByApplied3 = false;
wasOrderByApplied4 = true;
wasOrderByApplied5 = false;
wasOrderByApplied6 = true;
对于最后的结果,似乎每个查询询问的第三个问题是正确的,但后来我做了第三个查询(query3)并且结果在哪里:
wasOrderByApplied7 = false;
wasOrderByApplied8 = false;
wasOrderByApplied9 = false;
当我在订单后面添加一个位置时,问题结果为 false ,其中 true 。
有没有更好的方法来了解OrderBy是否应用于查询?
答案 0 :(得分:6)
这是我想到的一种可能的解决方案:
创建一个表达式访问者,检查表达式是否像这样调用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
{
//..
}
答案 1 :(得分:0)
你不需要知道什么。这毫无意义。如果您想要Take
或Skip
某些元素,您需要在此之前订购它们。请考虑以下
class Animal
{
public int Weight { get; set; }
public int NumberOfLegs { get; set; }
}
...
public IEnumerable<Animal> TakeFive(IEnumerable<Animal> animals)
{
return animals.Take(5);
}
你会带五个动物?什么腿最多?还是那些更重的?还是那些重量较轻的?你不知道。但是,如果你改变这样的代码
public IEnumerable<Animal> TakeFive(IEnumerable<Animal> animals)
{
return animals.OrderBy(_ => .Weight).Take(5);
}
它开始有道理了。
您不仅可以将其应用于IEnumerable
,还可以应用于IQueryable
。如果您不知道订单是什么,则无需知道序列是否已订购。