Click here to Skip to main content
Click here to Skip to main content

Paging in any ASP.NET grid using SQL Server 2005

By , 14 Jul 2010
 

Introduction

This article helps to add paging to any ASP.NET/WinForms grid. The benefit of using this method is it doesn't fetch all the data at once, but only the required data from the database, thus improving the performance of the page by many folds when the amount of data is large.

Background

After working on different grid controls provided by ASP.NET for over 5 years and using the Microsoft technique of filling all the data in a dataset and then binding it to a grid control, I always used to think there has to be a better way of doing this because of the huge amount of data bound to the control.

Using the Code

My primary aim while using the Microsoft default technique was to show only a few records on a grid and allow paging on the grid. For doing this, I used to fetch all the data from the database, thinking although I am fetching all the data, it happens only once and thus paging becomes much easier and efficient.

But then, one day reality (the cons of this way) came crashing on me, when one fine day my application had almost a million records and the loading of the grid page became super slow. Now I had to search for a better way (the one I always used to think about ;-) ) which would allow me to only fetch the required rows from the database for displaying. And then the "ROW_NUMBER()" function of SQL came to my aid, and by using this function in my Stored Procedure, the performance of my page improved drastically (I can't think of a better word here). The updated Stored Procedure looks like below.

CREATE PROCEDURE [dbo].[GetEmployeesPage] 
( 
@RowFrom int, 
@RowTo int 
) 
AS 
BEGIN 
SET NOCOUNT ON; 
WITH IndexedEmployees AS 
( 
SELECT 
ROW_NUMBER() OVER (ORDER BY Id) AS rowIndex, 
Employees.* 
FROM 
Employees 
) 

SELECT * FROM IndexedEmployees WHERE rowIndex BETWEEN @RowFrom AND @RowTo 

SELECT COUNT(*) 
FROM 
Employees 

END 
GO

The Stored Procedure returns two results. The first one contains the data that has been paged on the basis of the RowFrom and RowTo parameters, and the second query returns the count of employees, and these can be used on the web page to decide on the paging parameters.

For example: if the 'Employees' table contains 54 rows, then based on the different paging parameters, this will be 1-10, 11-20, 21-30, 31-40, 41-50, 51-54. The second resultset will allow the developer to send the 51-54 parameter.

Points of Interest

The "ROW_NUMBER()" function of SQL Server 2005 is new, and is used to assign ranks to the result of a query. This rank can be used for the paging of records.

An analysis I did by using the traditional method and this method will be of a lot of interest to many of you. I used three ways to fetch data from a table having half a million records.

  • SqlDataAdapter.Fill() method takes 42 seconds to fetch the entire data.
  • SqlDataAdapter.Fill() method with a starting record and page size needs around 10 seconds to fetch page-wise data.

And using the method described above, the same data can be fetched in a fraction of 1 second.

This technique can be extended to add sorting to the grid view as well.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Anuj Khadloya
Technical Lead Kale Consultants Ltd.
India India
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralNot really .NETmembersecorbett13 Jul '10 - 3:32 
While this is useful for T-SQL, this isn't really a .NET article, is it? If it were, wouldn't it be easier to use the SqlDataAdapter.Fill method with a starting record and page size, no?
Scott E. Corbett
Software Engineer/Analyst

GeneralRe: Not really .NETmemberAnuj Khadloya13 Jul '10 - 21:38 
It should be considered as a .NET article for paging of data grid. A small analysis for a table consisting half a million records tells me that using
 
SqlDataAdapter.Fill method it takes around 42 seconds
SqlDataAdapter.Fill method with a starting record and page size needs around 10 seconds
And using the method described above it takes not even 1 second
 
So I feel this method will be a preferred for paging in a datagrid.
GeneralMy vote of 3membersecorbett13 Jul '10 - 3:28 
This isn't a .NET article. It's a SQL article, and there are easier ways in .NET to do this.
QuestionWhy would you run a query which returns a million records?memberKeith Worden13 Jul '10 - 1:22 
I think you should be looking at the options that allow the user to run a query which returns a million records. There's no way anybody is ever going to look through that many and once they realize how many there are they would run something which would return less records.
 
Personally I don't care how many records the query returns - I limit webpage output to 100 records; if what they want isn't there they need to refine their search.
AnswerRe: Why would you run a query which returns a million records?memberAnuj Khadloya13 Jul '10 - 22:50 
Thats what this article suggests. It provides a way to fetch required number of records (100 in your case scenario) and then fetch the next 100 when the client asks for the new set of records.
 
I hope this makes it clear.
 
Cheers Smile | :)
Anuj
GeneralRe: Why would you run a query which returns a million records?memberKeith Worden14 Jul '10 - 0:08 
I understand the function but I think you miss my point. What if the record the user was looking for was in the last 100,000? They would never scroll through 900,000 records to find it - they would adjust their search criteria to return far less records. So in my opinion there is no point having a facility which can handle return of a million records - the search function should always limit the number returned to a quantity the user can quickly scan.
GeneralRe: Why would you run a query which returns a million records?memberAnuj Khadloya14 Jul '10 - 0:26 
I agree with your point of view of having a search return limited number of rows. But it eventually depends on the requirement and is a very product specific thing. Possibly there is no logical filter that can be applied to the data or possibly the search criteria my user applies returns me 100 thousand rows.
 
Using the total number of counts I get from the query I can allow the user to navigate to all the possible pages. In case of a windows application I could provide a slider for paging data for a grid. And the query takes very small amount of time to execute making it my preferred option for paging even when I have already applied a search criteria.
 
- Anuj
GeneralGoodmemberYves12 Jul '10 - 12:59 
I did not know about ROW_NUMBER() ... that makes sense. Thank
GeneralRe: Goodmembersambasivam elayaraja12 Jul '10 - 21:05 
Use the below changes, it will avoid second result set for Rowcounts.

 
CREATE PROCEDURE [dbo].[GetEmployeesPage]
(
@RowFrom int,
@RowTo int
)
AS
BEGIN
SET NOCOUNT ON;
WITH IndexedEmployees AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY Id) AS rowIndex,COUNT(*) OVER () AS [ROWCOUNT],
Employees.*
FROM
Employees
)
 
SELECT * FROM IndexedEmployees WHERE rowIndex BETWEEN @RowFrom AND @RowTo
 

END
GO
GeneralRe: GoodmemberAnuj Khadloya14 Jul '10 - 0:55 
The second result count is used to determine the number of pages for the data. Hence it should not be deleted without giving enough consideration.
 
Cheers!!
- Anuj
GeneralMy vote of 4memberdebuggervn9 Jul '10 - 23:12 
Thanks your article so much
GeneralNot enough for an articlememberdigital man7 Jul '10 - 21:28 
Perhaps better as a tip/trick or blog post.
"If you think it's expensive to hire a professional to do the job, wait until you hire an amateur." Red Adair.
nils illegitimus carborundum
 
me, me, me

GeneralJust enough for an articlememberaboveunrefined8 Jul '10 - 3:14 
First, I'd like to say thanks for the information. This is a fine post and I'll probably have to use something like this down the road (if I'd like to go home at a reasonable hour!)
 
My opinion states that this is a brief article. Right to the point and shows me the trick.
 
It COULD be in tips and tricks instead, but who cares?
 
I hate useless posts, but I might as well join the bandwagon!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 14 Jul 2010
Article Copyright 2010 by Anuj Khadloya
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid