Question

I have the following abstract class which all of my Repositories inherit from:

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

I wanted to add another method for automatically paging an IQueryable<T> and returning a List<T> from the results:

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();
}

But, Skip requires that the source by IOrderedQueryable<T>. I tried changing the method signature to:

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

But Skip returns an IQueryable<T> so I receive the error Cannot convert source type 'System.Linq.IQueryable<T>' to target type 'System.Linq.IOrderedQueryable<T>'

How do I force the implementing class to send my method an IOrderedQueryable<T> and get my paginate method to work?

Was it helpful?

Solution

It sounds like you should might want to make Paginate still take an IOrderedQueryable<T> to validate at compile-time that you've started with something that's ordered - but you don't then need to assign back to the same variable. For example:

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();
}

And as Marc notes, it would probably be better to change the Take line to:

if (take.HasValue) result = result.Take(take.Value);

OTHER TIPS

The Queryable.Skip and Queryable.Take methods do not require this, but some providers (I'm thinking "EF" mainly) do insist on it; in which case the solution is simply: make sure the original query has an order. For example:

var query = {whatever}.OrderBy(x => x.Id); // identity column? why not...
var page = Paginate(query, ...);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top