ASP
.NET - Paginação com GridView e LINQ to SQL
O GridView é um controle fantástico mas tem um problema : na funcionalidade de paginação oferecida pelo controle os links de paginação são gerenciados via JavaScript. Assim, se por algum motivo o JavaScript for desabilitado ou o navegador do cliente não suportar JavaScript (tudo é possível) os links não funcionarão.
A classe GridView exibe os valores de uma fonte de dados em uma tabela onde cada coluna representa um campo e cada linha representa um registro.O Controlador GridView permite a você selecionar, classificar e editar esses itens |
Então neste artigo eu vou mostrar, com base em diversos artigos, especialmente os artigos encontrados em Scott Guthrie's series of blog entries on LINQ to SQL , como criar uma alternativa de paginação para o controle GridView usando Html.
Eu não vou entrar em detalhes sobre a LINQ to SQL (veja as referências para detalhes) apenas mostrarei sua utilização prática.
Os recursos usados neste artigo são:
Criando o projeto
Abra o Visual Web Developer 2010 Express Edition e crie um novo projeto usando a linguagem Visual Basic e o template ASP .NET Empty Web Application com o nome PaginacaoGridViewLinqToSQL;
![]() |
No menu Project clique em Add New Item e selecione o template LINQ to SQL Classes informando o nome Northwind.dbml e clicando no botão Add;
![]() |
O arquivo Northwind.dbml contém o arquivo XML com informações sobre o leiaute das tabelas que foram mapeadas e também o descrito contendo as classes geradas pelo mapeamento. Após encerrar o mapeamento você já terá acesso aos recursos do LINQ To SQL com direito a intellisense completo das informações referente as tabelas mesmo sem conhecer nada sobre elas.
A seguir selecione a conexão com o banco de dados Northwind.mdf (se ela não existir você deverá adicioná-la);
Selecione as tabelas : Category, Products, Order Details e Orders e arraste-as para o descritor LINQ to SQL de forma a gerar o modelo mostrado na figura abaixo:
![]() |
Agora inclua uma página Web Form no projeto : menu Project -> Add New Item , template Web Form , nome Paginacao.aspx;
![]() |
Vamos incluir um controle GridView (ID=gdvDados) e um controle Literal na página conforme mostra a figura a seguir:
![]() |
Em seguida no code-behind do arquivo Paginacao.aspx.vb inclua o seguinte código no evento Load da página:
Protected Sub
Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load Dim db As New NorthwindDataContext() Dim consulta = From p In db.Products Where p.Order_Details.Count > 2 Select New With { _ .ID = p.ProductID, _ .Nome = p.ProductName, _ .NumeroPedidos = p.Order_Details.Count, _ .Receita = p.Order_Details.Sum(Function(o) o.UnitPrice * o.Quantity)} gdvDados.DataSource = consulta gdvDados.DataBind() End Sub |
Na sintaxe acima a consulta LINQ utiliza o novo padrão de operadores de consulta, disponibilizados a partir da versão 2008 do Visual Studio e Visual Web Developer. É uma abreviação declarativa que é compilada em um método explícito de invocação contra as classes de entidade criada pelo designer. O código compilado utiliza os novos métodos de extensão e expressões Lambda.
A sintaxe da consulta será traduzida para uma instrução SQL, e, sem saber muito sobre os operadores padrão de consulta LINQ ou sintaxe, você já pode imaginar que ele irá retornar o ProductID sob um alias ID, o ProductName (Nome), o total de Pedidos para cada produto (NumeroPedidos) e as receitas por produto, calculado multiplicando o preço unitário do produto pela quantidade vendida de todos os pedidos (Receita).
O resultado será retornado para uma variável consulta do tipo <Product> IEnumerable que pode ser vinculada a qualquer controle que suporta IEnumerable. No momento, porém, o código não vai fazer nada, porque a execução foi adiada até que você realmente tente fazer algo com os resultados, tais como iterar sobre eles.
O código será executado no ponto em que DataBind() for chamado. No entanto, isso realmente não serve ao nosso propósito. Se o GridView está configurado para a paginação, as ligações padrão Javascript irão aparecer, e se não estiver, todos os resultados aparecerão. Como nosso GridView atual não está configurado. Então, vamos implementar a paginação dentro do code-behind.
O LINQ tem muitos operadores úteis, dois dos quais são : Skip () e Take(). Eles são usados em cenários como o de paginação, porque eles são convertidos para o uso de ROW_NUMBER com o SQL Server, que lhe permite saltar um determinado número de linhas, e só tomar uma série limitada a partir desse ponto.
Isto significa basicamente que se você quiser exibir somente 10 registros por página, você só precisa selecionar 10 registros, e não todo o conjunto de resultados como é o padrão para o GridView e um SqlDataSource. Então, precisamos adicionar o código para calcular em qual página estamos para que possamos dizer ao banco de dados quantas linhas saltar e pegar. Precisamos também saber o total de páginas que existem nos resultados da consulta. Para isso incluímos o seguinte código:
Dim
totalRegistros As Integer = consulta.Count() Dim tamanhoPagina As Integer = 10 Dim TotalPaginas As Integer = totalRegistros \ tamanhoPagina |
Vamos entender o código acima:
- A variável totalRegistros
usa o método Count() e o LINQ traduz isso para uma consulta SELECT
COUNT (*) quando ela for executada no banco de dados;
- A variável tamanhoPagina define o número de
registros a serem exibidos por página ;
- A variável totalPaginas calcula o número
total de páginas necessárias para mostrar todos os registros, e
é simplesmente o resultado do número de registros dividido pelo
tamanho da página retornada como um número inteiro;
Agora falta criar o Html para realizar a paginação conforme o código a seguir:
If
totalRegistros Mod 10 > 0 Then totalPaginas += 1 End If Dim LinhaInicio As Integer = Convert.ToInt32(Request.QueryString("LinhaInicio")) Dim sb As New StringBuilder() For i As Integer = 0 To TotalPaginas - 1 Dim numPagina As Integer = i + 1 sb.Append("<a href=""Paginacao.aspx?LinhaInicio=" & tamanhoPagina * i & """>" & numPagina.ToString() & "</a> ") Next |
Se o resultado do modulo do número total de registros dividido pelo número de páginas for maior que 0 (totalRegistros Mod 10 > 0), temos de adicionar uma página ao total para atender os registros extras. Dai usamos um StringBuilder em um ciclo para a construção do html que irá conter os links de paginação.
Note que os links das páginas incluem um valor string , LinhaInicio, e cada vez que loop for executado, este valor é definido como tamanhoPagina (10) * o valor do contador do loop.
Para concluir, os registros precisam ser vinculados ao GridView e os links de paginação aplicados ao controle Literal conforme o código abaixo:
Literal1.Text =
"Página: " & sb.ToString() gdvDados.DataSource = consulta.Skip(LinhaInicio).Take(10) gdvDados.DataBind() |
O código completo pode ser visto a seguir:
Public
Class Paginacao Inherits System.Web.UI.Page Dim LinhaInicio As Integer Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim db As New NorthwindDataContext() Dim consulta = From p In db.Products Where p.Order_Details.Count > 2 Select New With { _ .ID = p.ProductID, _ .Nome = p.ProductName, _ .NumeroPedidos = p.Order_Details.Count, _ .Receita = p.Order_Details.Sum(Function(o) o.UnitPrice * o.Quantity)} Dim totalRegistros As Integer = consulta.Count() Dim tamanhoPagina As Integer = 10 Dim totalPaginas As Integer = totalRegistros \ tamanhoPagina If totalRegistros Mod 10 > 0 Then totalPaginas += 1 End If Dim LinhaInicio As Integer = Convert.ToInt32(Request.QueryString("LinhaInicio")) Dim sb As New StringBuilder() For i As Integer = 0 To TotalPaginas - 1 Dim numPagina As Integer = i + 1 sb.Append("<a href=""Paginacao.aspx?LinhaInicio=" & tamanhoPagina * i & """>" & numPagina.ToString() & "</a> ") Next Literal1.Text = "Página: " & sb.ToString() gdvDados.DataSource = consulta.Skip(LinhaInicio).Take(10) gdvDados.DataBind() End Sub End Class |
Executando o projeto iremos obter:
![]() |
Temos assim um GridView com recurso de paginação que funciona sem depender do JavaScript.
Pegue o projeto completo aqui:
PaginacaoGridViewLinqToSQL.zip
"Em verdade , em verdade vos digo que vem a hora, e agora é, em que os mortos ouvirão a voz do Filho de Deus, e os que a ouvirem viverão."(João-5:25)
Referências: