.NET - Usando Dapper Contrib
Hoje vamos apresentar o Dapper.Contrib, qual a sua proposta, e como ele pode ajudar quem usa o Dapper. |
Indo direto ao ponto o Dapper.Contrib é uma biblioteca 'helper' construída sobre o Dapper que inclui recursos para facilitar a vida de quem usa o Dapper.
Ele foi criado para facilitar ainda mais o desenvolvimento com o Dapper, reduzindo a quantidade de código necessário para executar operações comuns de CRUD (Create, Read, Update, Delete).
O Dapper.Contrib fornece um conjunto de atributos que você pode adicionar às suas classes de modelo para definir o mapeamento entre as propriedades da classe e as colunas do banco de dados. Com esses atributos, você pode definir de forma simples e declarativa como as operações de inserção, atualização e exclusão devem ser realizadas.
Aqui estão alguns dos principais recursos do Dapper.Contrib:
Desta forma o Dapper.Contrib é uma extensão do Dapper que adiciona recursos extras, como mapeamento automático, operações CRUD simplificadas e suporte a relacionamentos entre tabelas ajudando a reduzir a quantidade de código que você precisa escrever ao trabalhar com o Dapper, tornando o desenvolvimento de acesso a banco de dados mais rápido e fácil.
Usando o Dapper.Contrib
Para usar este recurso no seu projeto .NET basta incluir o pacote nuget Dapper.Contrib :
Ao instalar o pacote Dapper.Contrib o Dapper vem junto como uma dependência do pacote.
A seguir precisamos criar o banco de dados e as tabelas e a seguir criar as entidades definindo propriedades que devem mapear para as respectivas tabelas do banco de dados que desejamos usar.
Assim criamos o banco de dados Cadastro e a tabela Eventos com a estrutura abaixo onde já incluímos um registro na tabela:
Importante destacar que definimos a coluna Id como sendo do tipo Identidade e assim ela será autoincremental e o SGBD vai gerenciar esta informação.
Agora vamos realizar um CRUD básico nesta tabela Eventos usando o Dapper.Contrib.
Vamos criar uma entidade Evento com o seguinte código:
public class Evento { public int Id { get; set; } public int LocalId { get; set; } public string Nome { get; set; } public DateTime Data { get; set; } public DateTime DataCriacao { get; set; } } |
Em primeiro lugar, Dapper.Contrib requer um “Id” para poder atualizar um registro. No nosso caso, temos uma propriedade chamada “Id” e o Dapper.Contrib usa essa convenção e sabe que ela é nossa chave primária na tabela.
Mas, e se usarmos algo como “EventoId” como nossa chave primária ?
public class Evento { [Key] public int EventoId { get; set; } public int LocalId { get; set; } public string Nome { get; set; } public DateTime Data { get; set; } public DateTime DataCriacao { get; set; } } |
Basta
adicionar o
atributo “Key” da biblioteca
Dapper.Contrib para informar que é nossa chave primária.
Em seguida, também precisamos informar que o nome da classe seja o mesmo que o nome da
Tabela SQL, mas no plural. Então, no nosso caso, o nome da nossa classe é
Evento e ela espera que nossa tabela de banco de
dados seja chamada de “Eventos”.
[Table("Eventos"] public class Evento { [Key] public int EventoId { get; set; } public int LocalId { get; set; } public string Nome { get; set; } public DateTime Data { get; set; } public DateTime DataCriacao { get; set; } } |
Basta usar o atributo [Table("nome")] para definir para qual tabela do banco vamos mapear a entidade.
Além destes atributos temos outros atributos adicionais como:
Atributo | Descricao |
Key | Torna a coluna correspondente a coluna chave primária da tabela |
Table | Mapeia para uma tabela com o nome especificado |
ExplicitKey | Define que a propriedade é uma chave que não é gerada pelo banco |
Write | Define que a propriedade é de gravação ou não |
Computed | Especifica que a propriedade deve ser excluida da atualização |
Para ilustrar o uso dos recursos do Dapper.Contrib vamos criar uma aplicação Console no VS 2022 e instalar os pacotes :
Vamos criar um método estático para retornar um objeto IDbConnection :
static
IDbConnection GetDbConnection() { string connectionString = "Data Source=<seu_servidor>;Initial Catalog=Cadastro;Integrated Security=True"; return new SqlConnection(connectionString); } |
Ao usar IDbConnection, você pode fornecer diferentes implementações, como SqlConnection para SQL Server, MySqlConnection para MySQL ou OracleConnection para Oracle, sem alterar muito o restante do código. Isso ajuda a manter a flexibilidade e facilita a portabilidade do código.
Nesse código, o método GetDbConnection() retorna uma instância de IDbConnection usando a implementação específica SqlConnection. Dessa forma, se você precisar alterar o provedor de banco de dados, basta modificar o método GetDbConnection() para retornar a implementação correspondente, mantendo o restante do código inalterado.
Inserindo um evento
Inserir dados no
banco de dados é uma das operações CRUD que atuam em uma linha individual
inserindo uma linha.
A biblioteca Dapper.Contrib fornece o método de
extensão Insert para inserir dados no banco
de dados.
static
void
InserirEvento() { var evento = new Evento { LocalId = 3, Nome = "Meu novo Evento", Data = DateTime.Now, DataCriacao = DateTime.Now }; int eventoId; Console.WriteLine("\nCriar um novo Evento "); // Inserção using (var db = GetDbConnection()) { try { db.Open(); eventoId = (int)db.Insert(evento); db.Close(); Console.WriteLine($"Evento {evento.Nome} incluido com sucesso"); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } |
Podemos usar o método Insert para incluir múltiplos registro na base de dados:
static
void
InserirMultiplosEventos() { using (var db = GetDbConnection()) { List<Evento> eventos = new List<Evento>() { new Evento { Id = 4, LocalId=2, Nome = "Meu Evento Recente", Data = DateTime.Now, DataCriacao = DateTime.Now }, new Evento { Id = 5, LocalId=3, Nome = "Meu Novo Recente", Data = DateTime.Now, DataCriacao = DateTime.Now }, }; db.Insert<List<Evento>>(eventos); } } |
Buscando um evento pelo ID
Podemos recuperar um registro específico do banco de dados usando o método Get e passar o id como argumento.
static
void
BuscarEventoPorId() { Console.WriteLine("\nDigite o ID do evento:"); if (int.TryParse(Console.ReadLine(), out int eventoId)) { using (var connection = GetDbConnection()) { var eventoRecuperado = connection.Get<Evento>(eventoId); if (eventoRecuperado != null) { Console.WriteLine("Evento encontrado:"); Console.WriteLine($"ID: {eventoRecuperado.Id}"); Console.WriteLine($"Nome: {eventoRecuperado.Nome}"); Console.WriteLine($"Data: {eventoRecuperado.Data}"); Console.WriteLine($"Data de Criação: {eventoRecuperado.DataCriacao}"); } else { Console.WriteLine("\nEvento não encontrado."); } } } else { Console.WriteLine("\nID inválido."); } } |
Buscando todos os eventos
Podemos obter todos os eventos do banco de dados usando o método GetAll<T>() :
static
void
ListarEventos() { Console.WriteLine("\nEventos cadastradaos\n"); using (var db = GetDbConnection()) { List<Evento> eventos = db.GetAll<Evento>().ToList(); foreach (var evento in eventos) { Console.WriteLine($"Nome: {evento.Nome} \t Data: {evento.Data} "); } } } |
Atualizar um evento
A atualização de uma entidade existente é semelhante à inserção de uma nova entidade.
Para fazer isso podemos usar o método de extensão Update para atualizar os dados existentes no banco de dados.
static
void
AtualizarEvento() { Console.WriteLine("\nDigite o ID do evento a ser atualizado:"); if (int.TryParse(Console.ReadLine(), out int eventoId)) { using (var connection = GetDbConnection()) { var evento = connection.Get<Evento>(eventoId); if (evento != null) { Console.WriteLine("Digite o novo nome do evento:"); evento.Nome = Console.ReadLine(); bool atualizado = connection.Update(evento); if (atualizado) { Console.WriteLine("\nEvento atualizado com sucesso."); } else { Console.WriteLine("\nFalha ao atualizar o evento."); } } else { Console.WriteLine("\nEvento não encontrado."); } } } else { Console.WriteLine("ID inválido."); } } |
Podemos usar o método Update para atualizar múltiplos registros do banco de dados:
static
void
AtualizarMultiplosEventos() { using (var db = GetDbConnection()) { List<Evento> eventos = new List<Evento>() { new Evento { Id = 4, LocalId=2, Nome = "Meu Evento Recente Atualizado", Data = DateTime.Now, DataCriacao = DateTime.Now }, new Evento { Id = 5, LocalId=3, Nome = "Meu Novo Recente Atualizado", Data = DateTime.Now, DataCriacao = DateTime.Now }, }; db.Update<List<Evento>>(eventos); } } |
Excluir um evento
Excluir uma entidade é o mais fácil porque requer apenas um ID exclusivo para identificar a entidade que está sendo excluída.
O Dapper.Contrib fornece os métodos de extensão Delete e DeleteAll para excluir dados existentes do banco de dados.
static
void
ExcluirEvento() { Console.WriteLine("\nDigite o ID do evento a ser excluído:"); if (int.TryParse(Console.ReadLine(), out int eventoId)) { using (var connection = GetDbConnection()) { var evento = connection.Get<Evento>(eventoId); if (evento != null) { bool excluido = connection.Delete(evento); if (excluido) { Console.WriteLine("\nEvento excluído com sucesso."); } else { Console.WriteLine("\nFalha ao excluir o evento."); } } else { Console.WriteLine("\nEvento não encontrado."); } } } else { Console.WriteLine("\nID inválido."); } } |
Você também pode usar o método Delete para excluir vários registros passando a lista como um argumento para o método Delete.
static
void
DeletarMultiplosEventos() {
using
(var
db = GetDbConnection()) |
Temos assim uma visão geral dos recursos da biblioteca Dapper.Contrib na prática.
Pegue o projeto aqui: Crud_DapperContrib.zip
"A lei e os profetas duraram até João; desde então é anunciado o reino de Deus,
e todo o homem emprega força para entrar nele.
E é mais fácil passar o céu e
a terra do que cair um til da lei."
Lucas 16:16-17
Referências: