c# – 如何检查ObjectQuery表达式树中是否存在OrderBy

我正在使用T4为LINQ to Entities实体生成存储库.

存储库包含(除其他外)适合于分页的List方法. Supported and Unsupported Methods的文档没有提到它,但是你无法“调用”跳过无序的IQueryable.它会引发以下异常:

System.NotSupportedException: The method ‘Skip’ is only supported for
sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before
the method ‘Skip’..

我通过允许通过部分方法定义默认排序来解决它.但是我在检查表达式树是否确实包含OrderBy时遇到了问题.

我已将问题减少到尽可能少的代码:

public partial class Repository
{
    partial void ProvideDefaultSorting(ref IQueryable<Category> currentQuery);

    public IQueryable<Category> List(int startIndex, int count)
    {
        IQueryable<Category> query = List();
        ProvideDefaultSorting(ref query);
        if (!IsSorted(query))
        {
            query = query.OrderBy(c => c.CategoryID);
        }
        return query.Skip(startIndex).Take(count);
    }
    public IQueryable<Category> List(string sortExpression, int startIndex, int count)
    {
           return List(sortExpression).Skip(startIndex).Take(count);
    }
    public IQueryable<Category> List(string sortExpression)
    {
        return AddSortingToTheExpressionTree(List(), sortExpression);
    }
    public IQueryable<Category> List()
    {
           NorthwindEntities ent = new NorthwindEntities();
           return ent.Categories;
    }

    private Boolean IsSorted(IQueryable<Category> query)
    {
        return query is IOrderedQueryable<Category>; 
    }
}

public partial class Repository
{
    partial void ProvideDefaultSorting(ref IQueryable<Category> currentQuery)
    {
        currentQuery = currentQuery.Where(c => c.CategoryName.Contains(" ")); // no sorting..
    }
}

这不是我真正的实现!

但我的问题是,我怎么能实现IsSorted方法?问题是LINQ to Entities查询始终是ObjectQuery类型,它实现了IOrderedQueryable.

那么我应该如何确保表达式树中存在OrderBy方法?是解析树的唯一选择吗?

更新
我添加了另外两个重载,以明确它不是关于如何向存储库添加排序支持,而是如何检查ProvideDefaultSorting部分方法是否确实已将OrderBy添加到表达式树.

问题是,第一个部分类是由模板生成的,而部分类的第二部分的实现是由团队成员在另一个时间完成的.您可以将它与.NET实体框架生成EntityContext的方式进行比较,它允许其他开发人员使用扩展点.所以我想尝试使其健壮,并且在ProvideDefaultSorting未正确实现时不会崩溃.

所以问题可能更多,我如何确认ProvideDefaultSorting确实在表达式树中添加了排序.

更新2
新问题得到了回答,并被接受,我想我应该更改标题以更多地匹配问题.或者我应该保留当前的标题,因为它会引导人们遇到同样的问题吗?

最佳答案
您可以在ProvideDefaultSorting的返回类型中解决此问题.此代码不构建:

    public IOrderedQueryable<int> GetOrderedQueryable()
    {
        IQueryable<int> myInts = new List<int>() { 3, 4, 1, 2 }.AsQueryable<int>();
        return myInts.Where(i => i == 2);
    }

这段代码构建,但是阴险,编码器得到他们应得的.

    public IOrderedQueryable<int> GetOrderedQueryable()
    {
        IQueryable<int> myInts = new List<int>() { 3, 4, 1, 2 }.AsQueryable<int>();
        return myInts.Where(i => i == 2) as IOrderedQueryable<int>;
    }

与ref相同的故事(这不构建):

    public void GetOrderedQueryable(ref IOrderedQueryable<int> query)
    {
        query = query.Where(i => i == 2);
    }

转载注明原文:c# – 如何检查ObjectQuery表达式树中是否存在OrderBy - 代码日志