Há momentos em que o result-set da base de dados é muito grande, ou seja, é retornado ao cliente uma grande quantidade de registros, o que pode custar muito caro para o mesmo pois recebe todos os registros e exibe apenas os registros que se enquadram na página atual, e limitando ao número de registros por páginas.
A paginação de dados vem justamente para suprir esta necessidade, podendo dar ao usuário uma forma mais simples de navegar pelo result-set e consequentemente, a aplicação ganha muito em performance. O controle GridView já fornece uma arquitetura que permite a paginação automática de registros.
A forma de como habilitar esta opção é idêntica à ordenação de colunas que fizemos anteriormente, ou seja, deve-se clicar na Smart Tag do controle GridView e marcar o CheckBox chamado Enable Paging, como é ilustrado na figura abaixo:
|
|
| Figura 1 – Habilitando a Paginação de Registros. |
Habilitando esta opção, o controle GridView já fará a paginação dos registros automaticamente. Através do código HTML abaixo da página ASPX, vemos como o mesmo ficou configurado:
<asp:GridView
ID="GridView1"
runat="server"
AllowPaging="True"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1"
PageSize="2">
<Columns>
<asp:BoundField
DataField="Nome"
HeaderText="Nome" />
<asp:BoundField
DataField="Email"
HeaderText="Email" />
</Columns>
</asp:GridView>
|
|||
| ASPX | |||
Uma nova propriedade é apresentada: PageSize. Ela é responsável por definir a quantidade de registros que serão apresentados por página.
Utilizando o objeto SqlDataSouce
Como neste objeto temos a propriedade DataSourceMode, onde definimos qual será a forma de recuperar os dados da fonte de dados (Dataset ou DataReader), infelizmente ele não pode ser definido como DataReader, pois para efetuar a paginação o objeto deverá obrigatoriamente implementar a interface ICollection, que é somente o caso do objeto Dataset. Vale lembrar que isso já é um problema conhecido nas versões 1.x do ASP.NET.
Para conseguir a paginação de forma automática temos que definir a propriedade DataSourceMode como Dataset ou omití-la. Mas é importante dizer que nada impedirá você de criar uma paginação e controle customizados para esta situação.
Utilizando o objeto ObjectDataSouce
Ao utilizar este tipo de objeto temos que fazer alguns ajustes para habilitar a paginação no controle GridView. Apesar de existir algumas formas diferentes de se fazer, no exemplo mostrado abaixo a paginação retornará apenas os registros pertinentes a página solicitada pelo usuário. Logo a Stored Procedure responsável por retornar estes registros deve receber dois parâmetros:
- PageNumber – O número da página requisitada pelo usuário.
- PageSize – Quantidade de registros por página.
Abaixo é exibida a Stored Procedure que utiliza subqueries para retornar a quantidade de registros de uma determinada página:
ALTER PROCEDURE dbo.CustomPaging
@PageSize As Int,
@PageNumber As Int AS
DECLARE @COUNTER As Int
SET @COUNTER = (SELECT COUNT(*) FROM Usuario)
IF @PageNumber = 0
SET @PageNumber = 1
SELECT Nome FROM Usuario
WHERE UsuarioID IN
(SELECT TOP(@PageSize) UsuarioID FROM Usuario
WHERE UsuarioID NOT IN
(SELECT TOP(@PageSize * (@PageNumber - 1)) UsuarioID FROM Usuario
ORDER BY Nome)
ORDER BY Nome)
ORDER BY Nome
RETURN @COUNTER
|
|||
| T-SQL | |||
Agora com o SQL Server 2005 e o SQL Server Express 2005, a cláusula TOP do T-SQL pode ser parametrizada, o que nas versões anteriores só conseguíamos através de uma query dinâmica. A quantidade total de registros (que utilizamos a função COUNT para recuperar) é necessária, pois o objeto ObjectDataSource precisa desse valor para calcular as páginas à serem exibidas ao usuário.
Depois da Stored Procedure pronta vamos analisar a classe de negócios que receberá os parâmetros e executará a Stored Procedure acima. Abaixo o código da classe de negócios:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Web.Configuration;
using System.Collections.Generic;
public class Paging
{
private int _count = 0;
public int TotalUsuarios(){
return this._count;
}
public List ResgataUsuarios(int pageSize, int pageNumber)
{
List coll = new List();
SqlConnection conn = new SqlConnection(
WebConfigurationManager.ConnectionStrings["ConnString"].ConnectionString);
SqlCommand cmd = new SqlCommand("CustomPaging", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@PageSize", pageSize);
cmd.Parameters.AddWithValue("@PageNumber", pageNumber);
cmd.Parameters.AddWithValue("@RETURN_VALUE", 0).Direction =
ParameterDirection.ReturnValue;
SqlDataReader dr = null;
try
{
conn.Open();
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dr.Read())
{
Usuario u = new Usuario();
u.Nome = dr.GetString(0);
coll.Add(u);
}
}
finally
{
if (dr != null)
dr.Close();
this._count =
Convert.ToInt32(cmd.Parameters["@RETURN_VALUE"].Value);
}
return coll;
}
}
|
|||
| C# | VB.NET | ||
Analisando o código acima, temos um membro privado na classe Paging, que é responsável por armazenar a quantidade total de registros da base de dados (ou da condição da cláusula SQL). O método ResgataUsuarios que recebe os parâmetros pageSize e o pageNumber, os quais já descrevemos acima suas utilidades, e através dele os mesmos são anexados à coleção de parâmetros do objeto SqlCommand que executa a Stored Procedure.
Através de um objeto SqlDataReader percorremos os registros da base de dados e populamos o objeto Usuario que posteriormente é adicionado à uma coleção genérica deste mesmo tipo.
Já o método TotalUsuarios retorna o valor contido dentro do membro privado denominado _count, o qual representa a quantidade total de registros da base de dados (ou da condição da cláusula SQL). Como já foi falado, o objeto ObjectDataSource ou qualquer outro tipo de paginação requer este valor para calcular e exibir a quantidade de páginas disponíveis ao usuário. Recuperamos este valor total através de um parâmetro do tipo RETURN_VALUE, que a Stored Procedure retorna para a aplicação.
Através do código HTML abaixo da página ASPX, vemos como configurar o objeto ObjectDataSource e o controle GridView corretamente:
<asp:ObjectDataSource
ID="ObjectDataSource1"
runat="server"
EnablePaging="True"
SelectCountMethod="TotalUsuarios"
StartRowIndexParameterName="pageNumber"
MaximumRowsParameterName="pageSize"
SelectMethod="ResgataUsuarios"
TypeName="Paging">
</asp:ObjectDataSource>
<asp:GridView
ID="GridView1"
runat="server"
AllowPaging="True"
AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1"
PageSize="2">
<Columns>
<asp:BoundField
DataField="Nome"
HeaderText="Nome" />
</Columns>
</asp:GridView>
|
|||
| ASPX | |||
Analisando o código HTML da página ASPX acima, vemos duas propriedades que já são de nosso conhecimento: a SelectMethod e TypeName, que foram descritas na seção sobre Tipos de DataSource. Abaixo são listadas as propriedades do objeto ObjectDataSource que ainda não analisamos:
-
EnablePaging – É necessário definir para True quando queremos habilitar a paginação de registros no objeto ObjectDataSource.
-
SelectCountMethod – Definimos nesta propriedade o nome do método da classe de negócios que é responsável por retornar a quantidade total de registros.
-
StartRowIndexParameterName – Baseando-se na classe de negócios que criamos acima, esta propriedade é definida com o nome do parâmetro (pageNumber) responsável pela página que o usuário requisitou.
-
MaximumRowsParameterName – Baseando-se na classe de negócios que criamos acima, esta propriedade é definida com o nome do parâmetro (pageSize) responsável pela quantidade de registros exibidos por página.
Já na configuração do controle GridView não se tem muito à fazer: temos que definir a fonte de dados a ser utilizada; habilitar a paginação através da propriedade AllowPaging e, finalmente, através da propriedade PageSize definir a quantidade de registros que serão exibidos por página. Realizados esses ajustes, o GridView já está pronto para realizar a paginação de registros sem a necessidade de definirmos os valores aos parâmetros, pois o controle GridView em conjunto com o objeto ObjectDataSource fará isso de forma transparente.
A imagem abaixo exibe o controle GridView já em funcionamento utilizando o objeto ObjectDataSource como fonte de dados:
|
|
| Figura 2 – GridView em funcionamento. |

