I need to merge these two methods in only one generalizing them. I know IQueryable implements IEnumerable, IOrderedQueryable implements IOrderedEnumerable and the first method seems to be useless if the second is present. But for some Entity Framework reasons the second one breaks the server-side query translating (Linq-to-SQL)
private static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
private static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
These methods break the DRY rule and it's awfully annoying.
Even if the code looks the same, they don't work on the same type and generics also can't be used, cause the where clause can only AND combine multiple given values.
So all you can do, is factor out the calculation logic, but if this is really better readable and maintainable really depends on your attitude.
private static bool TryCalculateRange(int totalCount, int pageLength, int page, out int skip, out int take)
{
skip = 0;
take = 0;
if(pageLength <= 0)
return false;
skip = pageLength * (page - 1);
if(skip >= totalCount)
skip = 0;
take = totalCount - skip;
if(take > pageLength)
take = pageLength;
return true;
}
public static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
public static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
}