IOrderedQueryable Skip and Take

时间:2014-02-04 11:53:12

标签: c# linq entity-framework-5 iqueryable

我有以下抽象类,我的所有存储库都继承自:

abstract class RepositoryBase<T> {
    void Add();
    void Delete();
    void SaveChanges();
}

我想添加另一种自动分页IQueryable<T>并从结果中返回List<T>的方法:

protected List<T> Paginate(IQueryable<T> content, int? skip, int? take)
{
    if (skip.HasValue) content = content.Skip(skip.Value);
    if (skip.HasValue && take.HasValue) content = content.Take(take.Value);
    return content.ToList();
}

但是,Skip要求来源IOrderedQueryable<T>。我尝试将方法签名更改为:

Paginate(IOrderedQueryable<T> content, int? skip, int? take)

Skip会返回IQueryable<T>,因此收到错误Cannot convert source type 'System.Linq.IQueryable<T>' to target type 'System.Linq.IOrderedQueryable<T>'

如何强制实现类发送我的方法IOrderedQueryable<T>并让我的paginate方法工作?

2 个答案:

答案 0 :(得分:5)

听起来你应该让Paginate仍然需要IOrderedQueryable<T>来验证编译时你已经开始使用已订购的东西 - 但是你然后不需要分配回相同的变量。例如:

protected List<T> Paginate(IOrderedQueryable<T> content, int? skip, int? take)
{
    // Different variable type so that we can assign to it below...
    IQueryable<T> result = content;
    if (skip.HasValue) result = result.Skip(skip.Value);
    if (skip.HasValue && take.HasValue) result = result.Take(take.Value);
    return result.ToList();
}

正如Marc所说,将Take行改为:

可能会更好
if (take.HasValue) result = result.Take(take.Value);

答案 1 :(得分:3)

Queryable.SkipQueryable.Take方法并不要求这样做,但有些提供商(我主要想的是“EF”)确实坚持这一点;在这种情况下,解决方案很简单:确保原始查询有订单。例如:

var query = {whatever}.OrderBy(x => x.Id); // identity column? why not...
var page = Paginate(query, ...);