Um dos grandes benefícios de utilizar o Dapper é sua velocidade e versatilidade no acesso a dados. No entanto, ele ainda deixa a desejar quando pensamos em mapeamento objeto-relacional (ORM). Para resolver essa limitação, a comunidade desenvolveu o Dapper.Contrib, uma biblioteca que simplifica o mapeamento de tabelas do banco de dados para classes utilizando anotações.
Com o tempo, a criação de classes de repositório pode se tornar um processo repetitivo e mecânico. Uma solução prática é implementar uma classe de repositório base, o que facilita o desenvolvimento e reduz a duplicação de código. Neste artigo, vamos explorar como criar uma estrutura de repositório genérico utilizando o Dapper.Contrib.
Criando a Interface do Repositório Base
Começamos criando uma interface que define os métodos genéricos do repositório. Utilizamos o tipo genérico T
para permitir que a interface seja reutilizada com qualquer classe que represente uma tabela do banco de dados.
internal interface IBaseRepository<T> where T : class
{
IEnumerable<T> GetAll();
T Get(int id);
T Get(string id);
long Insert(T entity);
long Insert(IEnumerable<T> entity);
bool Update(T entity);
bool Update(IEnumerable<T> entity);
bool Delete(T entity);
bool Delete(IEnumerable<T> entity);
}
Na interface, foram criados métodos para busca por Id usando tipos de dados inteiros e strings. Dessa forma, podemos realizar consultas no banco de dados utilizando esses dois tipos de dados. Caso seu banco de dados utilize outro tipo de chave primária, como GUID, basta implementar o método correspondente na interface, e ele estará disponível para uso.
Implementando o Repositório Base
Em seguida, implementamos a interface utilizando o Dapper.Contrib. No exemplo abaixo, estamos acessando um banco de dados SQL Server e aproveitando os métodos embutidos do Dapper.Contrib, como Insert
, Update
, Delete
e Get
.
internal class BaseRepository<T> : IBaseRepository<T> where T : class
{
public bool Delete(T entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Delete(entity);
}
public bool Delete(IEnumerable<T> entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Delete(entity);
}
public IEnumerable<T> GetAll()
{
using (var conn = new SqlConnection(ConnectionString))
return conn.GetAll<T>();
}
public T Get(int id)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Get<T>(id);
}
public T Get(string id)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Get<T>(id);
}
public long Insert(T entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Insert(entity);
}
public long Insert(IEnumerable<T> entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Insert(entity);
}
public bool Update(T entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Update(entity);
}
public bool Update(IEnumerable<T> entity)
{
using (var conn = new SqlConnection(ConnectionString))
return conn.Update(entity);
}
public string ConnectionString => "Minha Connection String";
}
Definindo a Entidade com Anotações
Agora, podemos criar uma entidade que representa uma tabela no banco de dados. Utilizamos as anotações fornecidas pelo Dapper.Contrib, como [Table]
para mapear a tabela e [Key]
para definir a chave primária.
[Table("dbo.TABLE_MYFILE")]
internal class MyFile
{
[Key]
public int Id { get; set; }
public string Customer { get; set; }
public string FileName { get; set; }
public DateTime FileDate { get; set; }
public string FilePath { get; set; }
}
Criando o Repositório Específico
Com o repositório base criado, construir um repositório específico para a entidade MyFile se torna extremamente simples. Apenas herdamos a classe BaseRepository
e implementamos a interface correspondente.
internal class FileRepository : BaseRepository<MyFile>, IBaseRepository<MyFile>
{
// Implementações específicas, se necessário
}
Usando o Repositório
Agora, ao instanciar o repositório, temos acesso simples a toda a funcionalidade que o Dapper.Contrib nos proporciona. Podemos, por exemplo, inserir, consultar, atualizar ou excluir registros da tabela associada à entidade MyFile de maneira fácil e eficiente.
Aqui está um exemplo de como usar o FileRepository
para inserir um novo registro de arquivo no banco de dados:
class Program
{
static void Main(string[] args)
{
// Instanciando o repositório
var fileRepository = new FileRepository();
// Criando uma nova entidade de arquivo
var newFile = new MyFile
{
Customer = "João Silva",
FileName = "relatorio.pdf",
FileDate = DateTime.Now,
FilePath = "/documentos/relatorios/relatorio.pdf"
};
// Inserindo o novo arquivo no banco de dados
var insertedId = fileRepository.Insert(newFile);
// Exibindo o ID do arquivo inserido
Console.WriteLine($"Arquivo inserido com ID: {insertedId}");
// Recuperando o arquivo pelo ID
var retrievedFile = fileRepository.Get((int)insertedId);
// Exibindo as informações do arquivo recuperado
Console.WriteLine($"Arquivo Recuperado: {retrievedFile.FileName}, Cliente: {retrievedFile.Customer}");
// Atualizando o registro do arquivo
retrievedFile.FileName = "relatorio_atualizado.pdf";
fileRepository.Update(retrievedFile);
Console.WriteLine("Arquivo atualizado com sucesso.");
// Excluindo o registro do arquivo
fileRepository.Delete(retrievedFile);
Console.WriteLine("Arquivo excluído com sucesso.");
}
}
Explicação:
-
Instanciando o repositório: A classe
FileRepository
é instanciada para realizar operações no banco de dados. -
Inserindo um novo arquivo: Um novo objeto da entidade
MyFile
é criado e inserido no banco de dados usando o métodoInsert
. -
Recuperando o arquivo: O arquivo é recuperado pelo seu ID com o método
Get
. -
Atualizando o arquivo: O arquivo recuperado é atualizado, e as mudanças são salvas no banco de dados com o método
Update
. -
Excluindo o arquivo: Finalmente, o arquivo é excluído do banco de dados utilizando o método
Delete
.
Este exemplo simples demonstra como Dapper.Contrib pode ser utilizado de forma eficiente para realizar as operações mais comuns de inserção, consulta, atualização e exclusão de registros com o padrão de repositório.
Source link
lol