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

yos*_*bel 3 c# linq entity-framework

我需要知道在应用.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;
Run Code Online (Sandbox Code Playgroud)

结果在哪里:

wasOrderByApplied = true;
wasOrderByApplied2 = true;
wasOrderByApplied3 = false;

wasOrderByApplied4 = true;
wasOrderByApplied5 = false;
wasOrderByApplied6 = true;
Run Code Online (Sandbox Code Playgroud)

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

wasOrderByApplied7 = false;
wasOrderByApplied8 = false;
wasOrderByApplied9 = false;
Run Code Online (Sandbox Code Playgroud)

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

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

Yac*_*sad 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

MyVisitor visitor = new MyVisitor();

visitor.Visit(query.Expression);

if (visitor.HasOrderBy)
{
    //..
}
else
{
    //..
}
Run Code Online (Sandbox Code Playgroud)

  • 对于 C# 6,我建议使用“nameof(Queryable.OrderBy)”等来摆脱魔术字符串。 (2认同)