如何在调用 Skip() 和 Take() 后获得 IOrderedQueryable<T>?

How to get an IOrderedQueryable<T> after calling Skip() and Take()?

我有一个分页 class,其中包含一个 ApplyFilter() 方法,该方法过滤当前页面的行。由于分页通常仅在排序结果中有意义,因此此方法接受并 returns 一个 IOrderedQueryable<T>(而不仅仅是 IQueryable<T>)。

我是这样用的:

var query = DbContext.Items
            .Where(i => i.Value > 0)
            .OrderBy(i => i.SortColumn);

query = pagination.ApplyFilter(query);

但是我的 ApplyFilter() 方法有问题。

public IOrderedQueryable<T> ApplyFilter<T>(IOrderedQueryable<T> query)
{
    return query.Skip((CurrentPage - 1) * PageSize).Take(PageSize);
}

Skip()Take() 方法都是 return 和 IQueryable<T>,所以我得到一个错误,return 值无法从 IQueryable<T>IOrderedQueryable<T>.

如何使用 Skip()Take() 并且仍然有一个 IOrderedQueryable<T>

你可以做一些俗气的事情,比如

public IOrderedQueryable<T> ApplyFilter<T>(IOrderedQueryable<T> query)
{
    return query.Skip((CurrentPage - 1) * PageSize).Take(PageSize).OrderBy(i=>1);
}

至少对于 SQL 服务器而言,codegen 足够聪明,可以忽略 OrderBy。

或者将return类型改为IQueryable<T>,并且不要重复使用查询变量:

var q = db.Set<User>().OrderBy(u => u.id);
var q2 = ApplyFilter(q);

或者将参数和 return 类型更改为 IQueryable<T> 并在有人传递的参数不是 IOrderedQueryable<T>

时抛出 ArgumentException
public IQueryable<T> ApplyFilter<T>(IQueryable<T> query)
{
    if (query is IOrderedQueryable<T> oq )
    {
        return oq.Skip((CurrentPage - 1) * PageSize).Take(PageSize);
    }
    else
    {
        throw new ArgumentException("Query must be IOrderdQueryable<T>");
    }
}