.NET MAUI Blazor - CRUD básico com SQLite
Neste artigo vamos criar uma aplicação híbrida .NET MAUI Blazor e realizar o CRUD básico usando o SQLite. |
As aplicações .NET MAUI Blazor são aplicações híbridas que combinam a tecnologia Blazor, que permite a construção de interfaces de usuário interativas usando C# e HTML, com o framework .NET MAUI (Multi-platform App UI), que é uma evolução do Xamarin.Forms e permite a criação de aplicativos multiplataforma.
Com as aplicações .NET MAUI Blazor, você pode criar aplicativos que são executados em várias plataformas, como Windows, macOS, iOS e Android, compartilhando uma base de código comum. Essas aplicações utilizam o modelo de desenvolvimento baseado em componentes do Blazor, onde você pode criar componentes reutilizáveis em C# e marcá-los com sintaxe semelhante ao HTML.
As aplicações .NET MAUI Blazor permitem que você desenvolva a interface do usuário e a lógica de negócios usando a mesma linguagem e tecnologia em todas as plataformas suportadas. Isso significa que você pode escrever a lógica de negócios, manipulação de eventos e acesso a dados em C#, enquanto a interface do usuário é renderizada usando a tecnologia de renderização do Blazor.
Essa abordagem simplifica o desenvolvimento de aplicativos multiplataforma, pois você pode reutilizar a maior parte do código e da lógica de negócios entre as plataformas, reduzindo a duplicação de esforços. Além disso, você pode aproveitar o ecossistema do .NET, incluindo bibliotecas, ferramentas e recursos existentes, ao construir suas aplicações .NET MAUI Blazor.
Para
uma introdução ao assunto leia o artigo:
.NET
MAUI Blazor - Criando aplicações híbridas multiplataforma
Neste artigo vamos criar uma aplicação .NET MAUI Blazor para realizar o CRUD básico em informações sobre alunos representando pela entidade Aluno onde vamos usar o banco de dados SQLite.
recursos usados:
VS 2022
SQLite
.NET MAUI Blazor
Criando o projeto
No VS 2022 Community vamos criar um projeto usando o template .NET MAUI Blazor App e nomeá-lo como MauiBlazorAlunos.
Após criar o projeto vamos remover as referências que não vamos usar e a seguir incluir os seguintes pacotes nugets no projeto:
<ItemGroup> <PackageReference Include="sqlite-net-pcl" Version="1.8.116" /> <PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.5" /> <PackageReference Include="SQLitePCLRaw.core" Version="2.1.5" /> <PackageReference Include="SQLitePCLRaw.provider.dynamic_cdecl" Version="2.1.5" /> <PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.5" /> </ItemGroup> |
1- sqlite-
2- SQLitePCLRaw.bundle_green
versão
2.1.5
3- SQLitePCL.Raw.core versão
2.1.5
4- SQLitePCLRaw.provider.dynamic_cdecl
versão
2.1.5
5- SQLitePCLRaw.provider.sqlite3
versão 2.1.5
Ao usar o SQLite em uma aplicação .NET MAUI, você precisa incluir este cinco pacotes no seu projeto. Cada pacote desempenha um papel específico no acesso e funcionamento do SQLite no .NET.
Esses pacotes são necessários para permitir o acesso ao SQLite em uma aplicação .NET MAUI, fornecendo as funcionalidades e as abstrações necessárias para trabalhar com o banco de dados SQLite em diferentes plataformas suportadas.
Criando o domínio e os serviços
using
SQLite; using System.ComponentModel.DataAnnotations; namespace MauiBlazorAlunos.Data; public class Aluno { [PrimaryKey, AutoIncrement] public int AlunoId { get; set; } [Required] public string Nome { get; set; } [Required] public string Email { get; set; } [Required] public string Endereco { get; set; } [Required] public string Genero { get; set; } } |
Nesta classe estamos usando os atributos da biblioteca SQLite.NET para realizar o mapeamento da classe para a tabela no SQLite
Os
atributos mais comuns usados no .NET MAUI para mapear uma classe
para tabelas no SQLite são:
- [Table]: Este atributo especifica o
nome da tabela no banco de dados.
- [Column]: Este atributo especifica o
nome da coluna na tabela.
- [PrimaryKey]: Este atributo
especifica que a coluna é a chave primária da tabela.
- [NotNull]: Este atributo especifica
que a coluna não pode ser nula.
- [ForeignKey]: Este atributo
especifica que a coluna é uma chave estrangeira para outra tabela.
- [Unique]: Este atributo especifica
que a coluna deve ter valores únicos.
- [AutoIncrement]: Este atributo
especifica que a coluna deve ter um valor incrementado
automaticamente.
A seguir vamos criar uma pasta Services no projeto onde vamos definir o serviço criando a interface IAlunoService e a classe AlunoService onde vamos implementar as operações de acesso aos dados usando o SQLite:
1- IAlunoService
public
interface
IAlunoService { Task InitializeAsync(); Task<List<Aluno>> GetAlunos(); Task<Aluno> GetAlunoById(int alunoId); Task<int> AddAluno(Aluno aluno); Task<int> UpdateAluno(Aluno aluno); Task<int> DeleteAluno(Aluno aluno); } |
2- AlunoService
using
MauiBlazorAlunos.Data; using SQLite; namespace MauiBlazorAlunos.Services;public class AlunoService : IAlunoService{ private SQLiteAsyncConnection _dbConnection; public async Task InitializeAsync() { await SetUpDb(); } private async Task SetUpDb() { if (_dbConnection == null) { string dbPath = Path.Combine(Environment.GetFolderPath Environment.SpecialFolder.LocalApplicationData), "Aluno.db3"); _dbConnection = new SQLiteAsyncConnection(dbPath); await _dbConnection.CreateTableAsync<Aluno>(); } } public async Task<int> AddAluno(Aluno aluno) { return await _dbConnection.InsertAsync(aluno); } public async Task<int> DeleteAluno(Aluno aluno) { return await _dbConnection.DeleteAsync(aluno); } public async Task<int> UpdateAluno(Aluno aluno) { return await _dbConnection.UpdateAsync(aluno); } public async Task<List<Aluno>> GetAlunos() { return await _dbConnection.Table<Aluno>().ToListAsync(); } public async Task<Aluno> GetAlunoById(int alunoId) { var aluno= await _dbConnection.QueryAsync<Aluno>($"Select * From {nameof(Aluno)} where AlunoID={alunoId} "); return aluno.FirstOrDefault(); } } |
Nesse código , o caminho do banco de dados é definido usando Environment.GetFolderPath para obter o diretório especial LocalApplicationData, que é usado para armazenar dados específicos do aplicativo. Em seguida, é definido o nome do arquivo do banco de dados ("aluno.db3") e o caminho completo do banco de dados é obtido usando Path.Combine.
Temos o método InitializeAsync() que será responsável por configurar o banco de dados. O método SetUpDb() foi alterado para ser assíncrono e retornar uma Task, permitindo o uso de await para aguardar a criação da tabela.
Dessa forma, ao utilizar o serviço, você poderá chamar explicitamente o método InitializeAsync() para realizar a inicialização do banco de dados de forma assíncrona.
Agora temos que registrar o serviço criado na classe MainProgram:
builder.Services.AddSingleton<IAlunoService, AlunoService>();
Criando as páginas Razor
Vamos criar as páginas Razor na pasta Page mas antes vamos ajustar o código do arquivo NavMenu.razor da pasta /Shared criando os seguintes links no menu : Home , Alunos e Manutenção :
... <div class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="alunos"> <span class="oi oi-list" aria-hidden="true"></span> Alunos </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="add_aluno"> <span class="oi oi-dashboard" aria-hidden="true"></span> Manutenção </NavLink> </div> ... |
A seguir vamos definir o código a seguir no arquivo _Imports.razor :
@using
System.Net.Http @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 MauiBlazorAlunos @using MauiBlazorAlunos.Shared @using MauiBlazorAlunos.Data @using MauiBlazorAlunos.Services |
Na página Index.razor vamos exibir uma imagem alunos.png que esta contida na pasta wwwroot/images:
@page
"/" < h3>Alunos - 2023</h3><center> <img src="images/alunos.png" height="250" width="350"/> </center> |
Vamos criar o componente Alunos.razor que vai exibir a relação de alunos existentes com opção para Deletar ou Editar os dados de um aluno selecionado :
@page "/alunos"
@inject IAlunoService alunoService <h1>Alunos</h1> @if (alunos == null) } @code { protected override async Task OnInitializedAsync() private void EditaAluno(int alunoId) private async void DeletaAluno(Aluno aluno) |
No componente Manutencao.razor temos o código que permite incluir um novo aluno ou excluir um aluno selecionado:
@page "/add_aluno" @page "/update_aluno/{AlunoId:int}" @inject IAlunoService alunoService @inject NavigationManager navigation <h3>Manutenção</h3> <div class="form-group"> <div class="mt-2 form-group"> <div class="mt-2 form-group"> <div class="mt-2 form-group"> <button type="submit" @onclick="Manutencao" class="mt-2 btn btn-primary">Enviar</button> @code { [Parameter] private string Nome; private void SetGenero(string genero) protected async override Task OnInitializedAsync() private async Task Manutencao() int response = -1; if (response > 0) private void Retornar() public async Task<bool> Valida() if (string.IsNullOrEmpty(Email)) if (string.IsNullOrEmpty(Endereco)) if (string.IsNullOrEmpty(Genero)) |
Neste código basicamente criamos um formulário sem usar o EditForm para que os dados de um aluno possam ser informados e definimos a validação no método Valida().
Executando o projeto em um emulador Android teremos o seguinte resultado:
1- A tela inicial
2- A exibição dos itens do menu
3- A exibição da lista de alunos
4- A tela onde podemos incluir ou editar os dados do aluno
Pegue o código do projeto aqui: MauiBlazorAlunos.zip
"Mas agora, morrendo para aquilo que antes nos prendia, fomos libertados
da lei, para que sirvamos conforme o novo modo do Espírito, e não segundo a
velha forma da lei escrita."
Romanos 7:6
Referências: