Blazor - CRUD usando o Google Cloud Firestore - II
Hoje vamos continuar a criação da aplicação Blazor que realiza um CRUD básico usando o banco de dados Cloud Firestore. |
Continuando a primeira parte do artigo vamos definir o modelo de domínio, a camada de acesso aos dados e a API.
Criando o modelo de dominio
Vamos criar o nosso modelo de domínio no projeto Shared.
Inclua uma pasta Models neste projeto e nesta pasta crie a classe Aluno com o código abaixo:
using Google.Cloud.Firestore;
namespace Blazor_Firestorer.Shared.Models
{
[FirestoreData]
public class Aluno
{
public string AlunoId { get; set; }
[FirestoreProperty]
public string Nome { get; set; }
[FirestoreProperty]
public string Email { get; set; }
[FirestoreProperty]
public string Cidade { get; set; }
[FirestoreProperty]
public string Sexo { get; set; }
}
}
|
Observe que decoramos classe Aluno com o atributo [FirestoreData]. Isso nos permitirá mapear esse objeto para a coleção do Firestore. Apenas aquelas propriedades da classe, que são marcadas com o atributo [FirestoreProperty], são consideradas quando salvamos o documento em nossa coleção.
Não precisamos salvar o AlunoId em nosso banco de dados, pois ele é gerado automaticamente. Ao obter os dados, vincularemos o ID do documento gerado automaticamente à propriedade AlunoId.
Da mesma forma, usaremos a propriedade Data para vincular a data de criação da coleção enquanto buscamos o registro. Usaremos essa propriedade Data para classificar a lista de funcionários pela data de criação do arquivo. Portanto, não aplicamos o atributo [FirestoreProperty] a essas duas propriedades.
A seguir vamos criar a classe Cidade definindo a propriedade Nome:
using Google.Cloud.Firestore;
namespace Blazor_Firestorer.Shared.Models
{
[FirestoreData]
public class Cidade
{
public string Nome { get; set; }
}
}
|
Essa classe será usada para popular o dropdownlist exibindo a lista de cidades para o usuário.
Criando a camada de acesso a dados
Vamos criar a camada de acesso a dados no projeto Server.
Crie uma pasta Data no projeto Server e a seguir crie a interface IAlunoDAL onde iremos definir o contrato com os métodos para acesso persistência dos dados:
using Blazor_Firestorer.Shared.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Blazor_Firestorer.Server.Data
{
public interface IAlunoDAL
{
public Task<List<Aluno>> GetAlunos();
public void AddAluno(Aluno employee);
public void UpdateAluno(Aluno employee);
public Task<Aluno> GetAluno(string id);
public void DeleteAluno(string id);
public Task<List<Cidade>> GetCidades();
}
}
|
A seguir crie a classe AlunoDAL que deve herdar de IAlunoDAL e implementar o contrato definido conforme o código abaixo:
using Blazor_Firestorer.Shared.Models;
using Google.Cloud.Firestore;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Blazor_Firestorer.Server.Data
{
public class AlunoDAL : IAlunoDAL
{
string projectId;
FirestoreDb fireStoreDb;
public AlunoDAL()
{
string arquivoApiKey =
@"D:\_blazor\Blazor_Firestorer\Blazor_Firestorer\Server\FirestoreApiKey\blazorcrudfirestore-1565827c5156.json";
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", arquivoApiKey );
projectId = "blazorcrudfirestore";
fireStoreDb = FirestoreDb.Create(projectId);
}
public async Task<List<Aluno>> GetAlunos()
{
try
{
Query alunoQuery = fireStoreDb.Collection("alunos");
QuerySnapshot alunoQuerySnapshot = await alunoQuery.GetSnapshotAsync();
List<Aluno> listaAluno = new List<Aluno>();
foreach (DocumentSnapshot documentSnapshot in alunoQuerySnapshot.Documents)
{
if (documentSnapshot.Exists)
{
Dictionary<string, object> city = documentSnapshot.ToDictionary();
string json = JsonConvert.SerializeObject(city);
Aluno novoAluno = JsonConvert.DeserializeObject<Aluno>(json);
novoAluno.AlunoId = documentSnapshot.Id;
listaAluno.Add(novoAluno);
}
}
List<Aluno> listaAlunoOrdenada = listaAluno.OrderBy(x => x.Nome).ToList();
return listaAlunoOrdenada;
}
catch(Exception ex)
{
var erro = ex.Message;
throw;
}
}
public async Task<Aluno> GetAluno(string id)
{
try
{
DocumentReference docRef = fireStoreDb.Collection("alunos").Document(id);
DocumentSnapshot snapshot = await docRef.GetSnapshotAsync();
if (snapshot.Exists)
{
Aluno aluno = snapshot.ConvertTo<Aluno>();
aluno.AlunoId = snapshot.Id;
return aluno;
}
else
{
return new Aluno();
}
}
catch
{
throw;
}
}
public async void AddAluno(Aluno aluno)
{
try
{
CollectionReference colRef = fireStoreDb.Collection("alunos");
await colRef.AddAsync(aluno);
}
catch
{
throw;
}
}
public async void UpdateAluno(Aluno aluno)
{
try
{
DocumentReference alunoRef = fireStoreDb.Collection("alunos").Document(aluno.AlunoId);
await alunoRef.SetAsync(aluno, SetOptions.Overwrite);
}
catch
{
throw;
}
}
public async void DeleteAluno(string id)
{
try
{
DocumentReference alunoRef = fireStoreDb.Collection("alunos").Document(id);
await alunoRef.DeleteAsync();
}
catch
{
throw;
}
}
public async Task<List<Cidade>> GetCidades()
{
try
{
Query cidadesQuery = fireStoreDb.Collection("cidades");
QuerySnapshot cidadesQuerySnapshot = await cidadesQuery.GetSnapshotAsync();
List<Cidade> listaCidades = new List<Cidade>();
foreach (DocumentSnapshot documentSnapshot in cidadesQuerySnapshot.Documents)
{
if (documentSnapshot.Exists)
{
Dictionary<string, object> city = documentSnapshot.ToDictionary();
string json = JsonConvert.SerializeObject(city);
Cidade novaCidade = JsonConvert.DeserializeObject<Cidade>(json);
listaCidades.Add(novaCidade);
}
}
return listaCidades;
}
catch
{
throw;
}
}
}
}
|
Aqui estamos implementando os métodos:
Cabe destacar que no construtor da classe definimos o caminho do arquivo JSON na variável arquivoApiKey que contém as informações das configurações do projeto no Firestore.
public AlunoDAL()
{
string arquivoApiKey =
@"D:\_blazor\Blazor_Firestorer\Blazor_Firestorer\Server\FirestoreApiKey\blazorcrudfirestore-1565827c5156.json";
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", arquivoApiKey );
projectId = "blazorcrudfirestore";
fireStoreDb = FirestoreDb.Create(projectId);
}
|
Definimos também a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS que vai obter as informações do arquivo JSON.
A variável projectId deve ser definida como o ID do seu projeto Firestore e será usada para criar a instância de acesso ao Firestore na nuvem.
Essa instância, fireStoreDb , será usada para realizar todas as operações de acesso ao Firestore.
Não podemos esquecer de registrar o serviço definindo o código abaixo no método ConfigureServices da classe Startup do projeto Server:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IAlunoDAL, AlunoDAL>();
services.AddControllersWithViews();
services.AddRazorPages();
}
|
Criando o controlador AlunosController
Vamos criar agora a nossa API de acesso aos dados no projeto Server.
Na pasta Controllers crie o controlador AlunosController e defina o código abaixo neste arquivo:
using Blazor_Firestorer.Server.Data;
using Blazor_Firestorer.Shared.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Blazor_Firestorer.Server.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AlunosController : ControllerBase
{
private readonly IAlunoDAL _aluno;
public AlunosController(IAlunoDAL aluno)
{
_aluno = aluno;
}
[HttpGet]
public Task<List<Aluno>> Get()
{
return _aluno.GetAlunos();
}
[HttpGet("{id}")]
public Task<Aluno> Get(string id)
{
return _aluno.GetAluno(id);
}
[HttpPost]
public void Post([FromBody] Aluno aluno)
{
_aluno.AddAluno(aluno);
}
[HttpPut]
public void Put([FromBody] Aluno aluno)
{
_aluno.UpdateAluno(aluno);
}
[HttpDelete("{id}")]
public void Delete(string id)
{
_aluno.DeleteAluno(id);
}
[HttpGet("GetCidades")]
public Task<List<Cidade>> GetCidades()
{
return _aluno.GetCidades();
}
}
}
|
Note que o código está bem enxuto e já podemos partir para a definição da interface com o usuário no projeto Client.
Na próxima parte do artigo vamos criar os componentes Razor para acessar e persistir dados realizando o CRUD.
"Por isso não desfalecemos; mas, ainda
que o nosso homem exterior se corrompa, o interior, contudo, se renova de dia em
dia."
2 Coríntios 4:16
Referências:
ASP .NET Core - Implementando a segurança com .
ASP.NET Core MVC - Criando um Dashboard .
C# - Gerando QRCode - Macoratti
Dicas para boas práticas de programação
ASP .NET - Gerando QRCode com a API do Google
Visual Studio - Dicas de Produtividade VII
.NET - Dicas de site com livros gratuitos para ...
ASP .NET MVC 5 - 10 boas práticas que fazem a diferença
eBook - 25 dicas para melhorar o desempenho ...
Blazor Server - CRUD com Entity Framework ...
Blazor - Passando dados para Componentes -
ASP .NET Core - CRUD usando Blazor e Entity
ASP .NET Core Blazor - Gerenciando Usuários e Perfis
ASP .NET Core - Iniciando com o Blazor