DEV Community

[PT_BR] Repositório Genérico com Dapper.Contrib

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);
}
Enter fullscreen mode Exit fullscreen mode

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";
}
Enter fullscreen mode Exit fullscreen mode

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; }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Explicação:

  1. Instanciando o repositório: A classe FileRepository é instanciada para realizar operações no banco de dados.
  2. Inserindo um novo arquivo: Um novo objeto da entidade MyFile é criado e inserido no banco de dados usando o método Insert.
  3. Recuperando o arquivo: O arquivo é recuperado pelo seu ID com o método Get.
  4. Atualizando o arquivo: O arquivo recuperado é atualizado, e as mudanças são salvas no banco de dados com o método Update.
  5. 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.

Top comments (0)