Paging and the Entity Framework, Skip, and Take Part 1

Get the total count of pages. | Get the real page number. | Using Skip and Take to Page | The Actual Paging Controls

So something I’ve been doing a lot of lately is making quite possibly the best thing ever: String cheese wrapped in turkey bacon. But when I’m not doing that, I am working with a lot of ListViews and the entity framework. Now I know there are “built in” paging controls but I just haven’t liked what I’ve seen. So I took it upon myself one day to develop a repeatable system for paging. Say you have users and a bunch of invites that are attached to the users. You want to show a list of invites for a particular user, but you want a ListView that doesn’t show every invite… ie you need a pager. Well just so happens I have a solution, but as always you should consult a doctor before use.

First off you need a method to get the total count of pages meaning what the ceiling is when you page upwards. After all, if you go over the possible count of pages, you’ll just get no items returned and look kind of dumb.

There are three situations you have to look out for: You have less items that the required items per page (Say 10 rows but you display 20 row per page), you have a perfect division (20 rows and 20 row per page or 40 rows and 20 rows per page, ect), you have an uneven division (21 rows and 20 rows per page). First two are easy, third isn’t hard exactly but there are some catches.

public static Int32 TotalCountOfPages(Int32 rowCount, Int32 neededPageSize)
{
  Int32 returnValue;
  if(rowCount > 0)
  {
    if (rowCount <= neededPageSize)
    {
      returnValue = 1;
    }
    else
    {
      if ((rowCount % neededPageSize) == 0)
      {
        returnValue = rowCount / neededPageSize;
      }
      else
      {
        Decimal convertedPageSize =
         Convert.ToDecimal(neededPageSize);
        Decimal convertedRowCount =
         Convert.ToDecimal(rowCount);
        Decimal resultRounded =
          Math.Round(convertedRowCount / convertedPageSize);
        Decimal resultNonRounded =
          convertedRowCount / convertedPageSize;

        if (resultRounded < resultNonRounded)
        {
           returnValue =
            Convert.ToInt32(resultRounded + 1);
        }
        else
        {
           returnValue =
            Convert.ToInt32(resultRounded);
        }
      }
    }
  }
  else
  {
    returnValue = 0;
  }
  return returnValue;
}

Ok so first off, I assume this one is pretty obvious:

  if(rowCount > 0)

If there aren’t any rows, the there can’t be a page count.

Next take care the less rows than being shown per page:

  if (rowCount <= neededPageSize)
  {
    returnValue = 1;
  }

Simple enough. Now for the second part, a perfect division between rows and rows to show:

 if ((rowCount % neededPageSize) == 0)
 {
    returnValue = rowCount / neededPageSize;
 }

Basically, for those who don’t know mod or the % operator, that means there is no remainder. If there were, the result of rowCount % neededPageSize would not be 0 since Mod basically means “Give me what’s left over when I divide something by something else.”

Ok, this is where it gets a little messy as I have yet to find a good way to round a number up since, far as I know, there’s no way to do it with the .Net lib’ary. So, I had to come up with something clever… and when that failed I came up with this:

 Decimal convertedPageSize =
    Convert.ToDecimal(neededPageSize);
 Decimal convertedRowCount =
    Convert.ToDecimal(rowCount);
  Decimal resultRounded =
    Math.Round(convertedRowCount / convertedPageSize);
  Decimal resultNonRounded =
    convertedRowCount / convertedPageSize;

  if (resultRounded < resultNonRounded)
  {
      returnValue =
          Convert.ToInt32(resultRounded + 1);
  }
  else
  {
     returnValue =
       Convert.ToInt32(resultRounded);
  }

Ok so what’s going on here? First off, because trying to divide an integer by an integer gives me an integer, I had to covert some stuff to decimal. Why is that? When I divide them, I need to know if the number after the decimal is between 1 and 1.5 since Math.Round will round down in that case killing my ability to tell if I have enough pages.

Example: 19 rows and 10 per page will give me a 1.9 which Round will make 2. This is perfect since I need two pages to show the 19 rows. What if I have 14 rows and 10 per page? I get 1 from rounding. Uh oh. I really need two pages.

How do I get around this? Get the rounded version and the unrounded version. From there I know that if the unrounded version is greater than the rounded version I need an extra page.

So 14 rows / 10 per page = 1.4 unrounded and 1 rounded. 1.4 > 1, so that 1 page isn’t going to do it. I need to add one more page. Now if it 19 rows/10 per page I’ll get 1.9 unrounded and 2 rounded. 2 pages is exactly what I need and I don’t have to add anything.

Next post I’ll show the next needed method: How to tell if the page number being sent in (From the pager/UI) is actually valid. If not, then grab the last possible amount of records.

3 thoughts on “Paging and the Entity Framework, Skip, and Take Part 1”

  1. Well this could be out-of-date, but instead of the complex stuff, could you possibly get away with:

    returnValue = ((rowCount – (rowCount % neededPageSize)) / neededPageSize) + 1;

    1. Believe you me, there are probably a lot of better ways then what I posted. In fact, I’m pretty sure I’ve figured some out myself since I posted that.

Comments are closed.