Entity Framework Core - Paginação de dados
Neste tutorial vou mostrar uma forma simples de realizar a paginação de dados usando o EF Core. |
Para mostrar de forma prática a paginação vamos criar um projeto
ASP .NET Core MVC que vai acessar a tabela
Products do banco de dados
Northwind.mdf e paginar os dados.
Criando o projeto no VS 2019 Community
Abra no VS 2019 e clique em New Project;
A seguir selecione o template ASP .NET Core Web App(Model-View-Controller) com o nome Paginacao.
No projeto criado crie a pasta Paginacao e nesta pasta vamos definir 3 classes :
1- PagedResultBase - Classe base abstrata para resultados paginados, usada em views e Views Componentes;
using System;
namespace PaginacaoWeb.Paginacao
{
public abstract class PagedResultBase
{
public int CurrentPage { get; set; }
public int PageCount { get; set; }
public int PageSize { get; set; }
public int RowCount { get; set; }
public int FirstRowOnPage
{
get { return (CurrentPage - 1) * PageSize + 1; }
}
public int LastRowOnPage
{
get { return Math.Min(CurrentPage * PageSize, RowCount); }
}
}
}
|
Esta classe abstrata é a classe base que iremos usar para implementar a paginação.
2- PagedResult<T> - Classe fortemente tipada para resultados e propriedades do conjunto de resultados.
using System.Collections.Generic;
namespace PaginacaoWeb.Paginacao
{
public class PagedResult<T> : PagedResultBase where T : class
{
public IList<T> Results { get; set; }
public PagedResult()
{
Results = new List<T>();
}
}
}
|
A classe
PagedResult herda da classe
PagedResultBase.
3- Paginacao - Classe que define o método de
extensão GetPaged<T> que implementa a paginação.
using System;
using System.Linq;
namespace PaginacaoWeb.Paginacao
{
public static class Paginacao
{
public static PagedResult<T> GetPaged<T>(this IQueryable<T> query,
int page, int pageSize) where T : class
{
var result = new PagedResult<T>();
result.CurrentPage = page;
result.PageSize = pageSize;
result.RowCount = query.Count();
var pageCount = (double)result.RowCount / pageSize;
result.PageCount = (int)Math.Ceiling(pageCount);
var skip = (page - 1) * pageSize;
result.Results = query.Skip(skip).Take(pageSize).ToList();
return result;
}
}
}
|
Este é o método de extensão para IQueryable<T> que retorna uma página de resultados e alguns números que descrevem o conjunto de resultados.
Na pasta Models vamos criar a classe Product e a classe de contexto AppDbContext:
1- Product - Representa a o modelo de entidade que iremos mapear para acessar a tabela Products do Northwind.
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
}
|
2- AppDbContext - A classe de contexto que herda de DbContext:
using Microsoft.EntityFrameworkCore;
namespace PaginacaoWeb.Models
{
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
}
|
Agora vamos configurar o contexto como um serviço no arquivo Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
}
|
E vamos definir a string de conexão no arquivo appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=\\sqlexpress;Initial Catalog=Northwind;Integrated Security=True"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
|
Agora no controlador HomeController vamos incluir o código abaixo:
using Microsoft.AspNetCore.Mvc;
using PaginacaoWeb.Models;
using PaginacaoWeb.Paginacao;
using System;
namespace PaginacaoWeb.Controllers
{
public class HomeController : Controller
{
private readonly AppDbContext _ctx;
public HomeController(AppDbContext ctx)
{
_ctx = ctx ?? throw new ArgumentNullException(nameof(ctx));
}
public IActionResult Index(int page = 1)
{
var dataProducts = _ctx.Products.GetPaged(page, 10);
return View(dataProducts);
}
public IActionResult Privacy()
{
return View();
}
}
}
|
No controlador injetamos uma instância do contexto e usamos o método de extensão GetPaged() para realizar a paginação dos dados.
Agora só falta definir o código da view Index.cshtml na pasta /Views/Home:
@model PaginacaoWeb.Paginacao.PagedResult<Product>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>ProductId</th>
<th>ProductName</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
@{ var i = 1; }
@foreach (var product in Model.Results)
{
var rowNo = (Model.CurrentPage - 1) * Model.PageSize + i;
i++;
<tr>
<td>@rowNo</td>
<td>@product.ProductID</td>
<td>@product.ProductName</td>
<td>@product.UnitPrice</td>
</tr>
}
</tbody>
</table>
@for (var p = 1; p <= Model.PageCount; p++)
{
<a href="@Url.Action("Index", new { page = p })" class="btn btn-default">@p</a>
}
|
Executando o projeto teremos o seguinte resultado:
Simples e eficiente...
Pegue o projeto aqui : EFCorePaginacao.zip (sem as referências)
E estamos conversados...
"Bendirei o Senhor, que me
aconselha; na escura noite o meu coração me ensina!"
Salmos 16:7
Referências: