如何检查ObjectQuery <T>表达式树中是否存在OrderBy

Dav*_*man 6 c# linq generics linq-to-entities code-generation

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

存储库包含(除其他外)适合于分页的List方法.支持和不支持的方法的文档没有提到它,但是你不能Skip在无序上"调用" IQueryable.它会引发以下异常:

System.NotSupportedException:方法'Skip'仅支持LINQ to Entities中的排序输入.必须在方法'Skip'之前调用'OrderBy'方法.

我通过允许通过部分方法定义默认排序来解决它.但是我在检查表达式树是否确实包含一个问题时遇到了问题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..
    }
}
Run Code Online (Sandbox Code Playgroud)

这不是我真正的实现!

但我的问题是,我该如何实现该IsSorted方法?问题是,LINQ到实体查询的是类型的始终ObjectQuery,它实现IOrderedQueryable.

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

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

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

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

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

Amy*_*y B 1

您可以在 ProvideDefaultSorting 的返回类型中解决这个问题。此代码不构建:

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

这段代码可以构建,但很阴险,编码人员得到了他们应得的。

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

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

    public void GetOrderedQueryable(ref IOrderedQueryable<int> query)
    {
        query = query.Where(i => i == 2);
    }
Run Code Online (Sandbox Code Playgroud)