Dapper, aumentando a performance de projetos .Net Core

Utilizar ORMs (Object Relational Mapper) em projetos é uma prática comum, pois facilitam realizar operações CRUD (Create, Read, Update e Delete) em algum banco de dados e, em algumas situações, desenvolver mapeamentos e modelagens. Dentre os diversos ORMs existentes os mais famosos seriam o EntityFramework e NHibernate, os quais possuem diversas funcionalidades/ferramentas que ajudam o desenvolvedor. Contudo, quando há consultas envolvendo um grande volume de registros, utilizando tais ORMs a instrução não será executada da maneira mais performática possível. Com isso surge um problema relativamente preocupante e questionamentos para poder solucionar o mesmo.

Uma das alternativas seria utilizar o ADO.NET a qual utiliza instruções SQL, porém não é muito produtiva. Outra solução seria o Dapper, um Micro-ORM, cuja sua primeira versão foi lançada em 2011, o qual é extremamente poderoso. Na imagem abaixo, apresenta-se um pequeno benchmark.

Fonte: https://github.com/StackExchange/Dapper

Um pequena curiosidade sobre o Dapper é que a bíblia de todos os desenvolvedores, o Stackoverflow, foi desenvolvida utilizando o Dapper. Apesar de poderoso, apresenta limitações, pois com ele por si só não consegue-se fazer operações CRUD a partir de um objeto, utilizar LINQs e mapear propriedades e classes de acordo com o banco de dados. Neste contexto, é proposto soluções para poder utilizar o Micro-ORM em todos os cenários comuns e de maneira produtiva.

Para dar início, necessita-se criar um banco de dados e tabelas que servirão como modelo para o projeto a ser criado. Dá-se isso executando aseguinte instrução SQL:

Instrução SQL para criar banco de dados, tabelas e inserção de registros

Para efeito de demonstração, será criado um projeto simples. Inicialmente, inicia-se o Visual Studio, seleciona-se um projeto do tipo ASP.NET Core Web Application e escolhe-se a opção WebApi.

Com o projeto já configurado, deve-se instalar os seguintes pacotes no mesmo:

  • Install-Package Dapper
  • Install-Package Dapper.FluentMap
  • Install-Package Dommel
  • Install-Package Dapper.Fluent.Dommel

Com os pacotes já instalados, é sugerido ter as seguintes pastas:

  • Controllers
  • Data
  • Models

Estas pastas servirão para separar em camadas o código, onde cada uma irá ter uma responsabilidade específica.

Na pasta Models cria-se as seguintes classes:

  • BaseEntity
  • Client
Classe pai, onde será herdada por todas as outras classes tendo um Id, obrigatoriamente.
Classe modelo para apresentação

Nas pasta Controller, deve-se criar uma classe chamada de ClientController, onde ficará os end-points e, como é um projeto pequeno, ficará as regras de negócio para que o mesmo funcione.

Controller referente ao cliente

Deixado, propositalmente, para o final, a camada de acesso aos dados, vinculado a pasta Data, é onde ficará as configurações e implementações referente ao Dapper e suas extensões. Dentro desta pasta, cria-se as seguintes sub-pastas:

  • Context (responsável pela conexão com o banco de dados)
  • Map (responsável por mapear a classe e suas propriedades em conformidade com o nome da tabela e suas respectivas coluna a qual faz referência)
  • Repository (responsável por conter os métodos que irá realizar o CRUD)

Primeiramente, implementa-se a classe de contexto, pois é através dela que as outras funcionalidades poderão ser implementadas. Nesta classe utiliza-se a biblioteca MySql.Data.MySqlClient, para poder trabalhar com conexões no MySql.

Após criar o contexto, desenvolve-se os repositórios para realizar as operações de CRUD no banco de dados. Lembrando que em bancos MySql é ideal abrir a conexão e fechá-la logo após de realizar a(s) devida(s) operação(ões), pois é uma boa prática em .NET levando em consideração que o ADO.NET trabalha com o pool de conexões que controla a abertura e fechamento das mesmas, dixá-la sempre aberta expõe as tabelas além de haver perda de performance. Neste contexto, usa-se a instrução using, onde ao término do bloco, fecha-se executa o método Dispose e fecha a conexão. Para a contrução da classe utiliza-se a biblioteca Dommel.

Por fim, necessita-se mapear a classe de acordo com a tabela que criou-se no banco de dados. Pode-se perceber que ambas possuem algumas nomenclaturas divergentes, tais como o nome das colunas da tabela no banco de dados e o nome das propriedades da classe no projeto. Para resolver esta diferença, cria-se uma classe de mapeamento e utiliza-se a biblioteca Dapper.FluentMap.Dommel.Mapping.

Após criar a classe de mapeamento, precisa registrá-la no projeto, para que o mesmo reconheça-a e realize as devidas operações. Para isso, cria-se uma outra classe chamada RegisterMapping, onde utiliza-se as bibliotecas Dapper.FluentMap e Dapper.FluentMap.Dommel.

Com a classe criada, precisa-se instanciar a mesma ao iniciar o projeto. Para isso, utiliza-se um recurso chamado de injeção de dependência, o qual é uma técnica para obter o acoplamento flexível entre objetos e colaboradores, e utiliza-se um padrão de design chamado Singleton, todas essas operações será feita na classe Startup do projeto dentro do método ConfigureServices.

O projeto pode ser encontrado aqui: https://github.com/alex250195/modelo.dapper.

Com isso, nota-se que há possibilidades de utilizar vários recursos do Dapper, os quais estão presentes em outros ORMs mais populares, e manter um sistema mais performático.

Vale ressaltar que a Microsoft lançou o EF Core (EntityFramework Core) com desempenho muito superior ao convencional EF (EntityFramework), cumprindo o que havia prometido com relação a performance, contudo o Dapper ainda mantém a posição de ORM com maior desempenho.

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.