Blazor - Pagina de busca simples (PostgreSQL)
Hoje vamos recordar alguns conceitos básicos do Blazor e criar um projeto para acessar dados em um banco de dados PostgreSQL e criar uma página de busca. |
Hoje vamos recordar alguns conceitos do Blazor começando pelo data binding.
Continuando
a
primeira parte do artigo vamos agora definir os demais projetos.
O Blazor possui duas formas principais de vincular dados no lado do cliente.
No Blazor, a ligação de dados bidirecional é obtida com o atributo bind.
Você especifica a variável que deseja vincular dentro do atributo bind : <input @bind="@Variavel"/>
Nesse caso, @bind funciona com um manipulador onchange depois que a entrada perde o foco (como quando um usuário sai da tabulação).
Se quisermos que as atualizações ocorram enquanto o usuário digita e a capacidade de controlar qual evento aciona uma atualização podemos usar @bind-value.
Quando usamos @bind-value:event="event", podemos especificar um evento válido como oninput, keydown, keypress e assim por diante.
Nossa aplicação vai usar um banco de dados PostgreSQL para acessar os dados e vamos usar o EF Core na abordagem Code-First para criar o banco de dados e a tabela de exemplo.
Você pode fazer o download do PostgreSQL neste link: https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
Criando o projeto
Abra o VS 2022 e acione o menu Create New Project;
Na janela Add New Project selecione Blazor e a seguir o template Blazor Server App:
Informe o nome Blazor_SearchDemo e a seguir selecione as configurações conformea abaixo:
Após criar o projeto vamos limpar o contéudo da pasta Data e remover os componentes Counter , FetchData e SurveryPrompt do projeto.
Vamos criar neste projeto as pastas Context e Services e vamos incluir também os seguintes pacotes Nuget:
Você pode usar o comando install-package <nome_pacote> e as versões usadas são as mais recentes. Pode também usar o menu Tools selecione Nuget Package Manager -> Manage Nuget Packages for Solution.
Na pasta Data vamos criar a classe Cliente :
public class Cliente
{
public int ClienteId { get; set; }
[MaxLength(100)]
public string? Nome { get; set; }
[MaxLength(150)]
public string? Email { get; set; }
public int Idade { get; set; }
}
|
Na pasta Context vamos criar o arquivo AppDbContext que herda de DbContext e que contém o mapeamento ORM e onde vamos usar os recursos do Bogus para incluir 100 registros fake na base de dados:
using Bogus;
using Microsoft.EntityFrameworkCore;
namespace Blazor_SearchDemo.Data;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Cliente> Clientes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var ids = 1;
var clienteFaker = new Faker<Cliente>("pt_BR")
.RuleFor(c => c.ClienteId, f => ids++)
.RuleFor(c => c.Nome, f => f.Name.FullName(Bogus.DataSets.Name.Gender.Female))
.RuleFor(c => c.Email, f => f.Internet.Email(f.Person.FirstName).ToLower())
.RuleFor(c => c.Idade, f => f.Random.Number(8, 90));
// gera 100 Clientes
modelBuilder
.Entity<Cliente>()
.HasData(clienteFaker.GenerateBetween(100, 100));
}
}
|
Para saber como usar o Bogus veja o meu artigo : C# - Gerando Dados Fake com Bogus
No arquivo appsettings.json inclua a string de conexão :
{
"ConnectionStrings": {
"DefaultConnection": "User ID=postgres;Password=***;Host=localhost;Port=5432;Database=ClientesDB;Pooling=true;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
|
Estou usando o usuário padrão e sua senha na porta 5432 onde vamos criar o banco ClientesDB.
Neste momento podemos aplicar o Migrations e gerar o banco e a tabela ClientesDB usando os comandos:
1 -
Add-Migration Inicial -> gera o script
2 - Update-database -> aplica o script
Ao final teremos o banco de dados criado no PostgreSQL e podemos usar o pgAdmin4 para verificar isso. Acessando o pgAdmin iremos ver o resultado abaixo:
Na pasta Services vamos criar a interface IClienteService e a classe ClienteService para implementar os métodos para localizar dados.
1- IClienteService
public interface IClienteService
{
Task<List<Cliente>> GetClientesAsync();
Task<Cliente> GetClienteAsync(int id);
Task<List<Cliente>> GetClientePorNomeAsync(string nome);
}
|
2- ClienteService
using Blazor_SearchDemo.Data;
using Microsoft.EntityFrameworkCore;
namespace Blazor_SearchDemo.Services;
public class ClienteService : IClienteService
{
private readonly AppDbContext _context;
public ClienteService(AppDbContext context)
{
_context = context;
}
public async Task<Cliente> GetClienteAsync(int id)
{
return await _context.Clientes.FirstOrDefaultAsync(c => c.ClienteId == id);
}
public async Task<List<Cliente>> GetClientePorNomeAsync(string nome)
{
return await _context.Clientes.Where(c => c.Nome.Contains(nome)).ToListAsync();
}
public async Task<List<Cliente>> GetClientesAsync()
{
return await _context.Clientes.ToListAsync();
}
}
|
Agora vamos registrar o serviço do contexto e o serviço do cliente na classe Program :
... var connection = builder.Configuration.GetConnectionString("DefaultConnection");builder.Services.AddDbContext<AppDbContext>(options => var app = builder.Build();... |
Agora, neste primeiro exemplo, vamos usar o componente Index.razor substituindo o código gerado pelo código abaixo:
@page
"/" < PageTitle>Index</PageTitle>< h2>Clientes</h2> |
No arquivo _Imports.razor vamos incluir o seguinte código:
@using
System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using Blazor_SearchDemo @using Blazor_SearchDemo.Shared @using Blazor_SearchDemo.Pages @using Blazor_SearchDemo.Data @using Blazor_SearchDemo.Services |
A seguir vamos incluir na pasta Pages um novo componente Razor chamado Clientes.razor :
@page "/clientes"
@inject IClienteService _service;
<h3>Lista de Clientes </h3>
<hr />
@if (_render)
{
<td>
<input type="text" placeholder="Nome do cliente" @bind-value="ocliente.Nome" />
<button class="btn-primary" @onclick="@ProcuraCliente">
Procurar Cliente
</button>
</td>
<table class="table">
<tr>
<th>Id</th>
<th>Nome</th>
<th>Email</th>
<th>Idade</th>
</tr>
@foreach (var item in lista)
{
<tr>
<td>@item.ClienteId</td>
<td>@item.Nome</td>
<td>@item.Email</td>
<td>@item.Idade</td>
</tr>
}
</table>
<h4>total : @lista.Count</h4>
}
else
{
<h4>Carregando...</h4>
}
@code {
List<Cliente>? lista;
private bool _render = false;
Cliente ocliente = new Cliente();
public string? nome { get; set; }
async Task ProcuraCliente()
{
nome = ocliente.Nome;
lista = await _service.GetClientePorNomeAsync(nome);
_render = true;
StateHasChanged();
}
protected override async Task OnInitializedAsync()
{
lista = await _service.GetClientesAsync();
_render = true;
}
}
|
Vamos entender o código:
Injetamos o serviço IClienteService usando a diretiva @inject
Definimos o input type onde usamos o atributo @bind-value vinculando a oCliente.Nome
Criamos um button e no evento onclick vamos chamar o método ProcuraCliente.
Observe que o código de marcação possui um @if avaliando o valor da variável boolean _render. Isso é feito para evitar o código que usa a lista de clientes seja acessando visto que view pode ser renderizada antes do evento OnInitializedAsync().
No método ProcuraCliente estamos usando o serviço e acessando os dados e informando definindo o valor de _render como true para informar que a view pode ser renderizada com os dados.
Precisamos usar StateHasChanged para atualizar a interface com o usuário.
Executando o projeto teremos:
Pegue o projeto aqui: Blazor_SearchDemo.zip ...
"O meu mandamento é este: Que vos ameis uns aos outros, assim como eu vos amei."
João 15:12
Referências:
NET - Unit of Work - Padrão Unidade de ...