My Attempt at LINQ Pagination

October 16, 2009

Today I’ve been diving into an easy way to paginate record sets in my applications.  Searching around the internet yielded several good walkthroughs on how to do this.  My favorite way came from my friend, Kevin Hazzardh, He discussed using the Skip() and Take() extension methods to form fit LINQ into building a SQL statement that’ll do all the heavy lifting for you.

Copying from Kevin’s example, I built the following code snippet:

int pageNumber = 1;
int pageSize = 20;

using (var entity = new Entities())
{
	var recordSet = (from r in entity.SomeTable
			orderby r.SomeID
			select r);
	recordSet = recordSet.Skip((pageNumber - 1) * pageSize).Take(pageSize);

	return recordSet;
}

What’s nice about the following code is that since LINQ is lazy loading, the SQL built doesn’t actually execute until we need it too.  The days of returning full datasets are done (yes, we’re still doing that on some projects). 

I went the next step to see if I could build an extension method of my own that did all of the above for me automatically.  Here was the result I came up with:

public static class ExtensionMethods
{
	public static IQueryable<t> Paginate<t>(this IQueryable<t> content, int pageNumber, int pageSize)
        {
            return content.Skip((pageNumber - 1)*pageSize).Take(pageSize);
        }
}

This extension method takes the query returned from LINQ (an IQueryable), and applies the additional constraints to it.  Here is the first example using my new extension method:

int pageNumber = 1;
int pageSize = 20;

using (var entity = new Entities())
{
	var recordSet = (from r in entity.SomeTable
			orderby r.SomeID
			select r);
	recordSet = recordSet.Paginate(pageNumber, pageSize);

	return recordSet;
}

 

Ta da!  Hopefully that makes sense.  I’m open to other suggestions and comments.  I’m learning that if I take about my thought processes on certain problems, that I receive a ton of great feedback from those who listen.