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.

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.
Criação do banco de dados
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:
Criação do projeto
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.


Instalação de pacotes
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
Estruturação do projeto
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
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.
Configuração da camada de acesso aos dados
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.
Conclusão
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.
Referências
- http://dapper-tutorial.net/
- http://netcoders.com.br/acesso-a-dados-com-dapper-net/
- http://netcoders.com.br/acesso-a-dados-com-dapper-net/
- https://medium.com/@renato.groffe/dapper-exemplos-de-utiliza%C3%A7%C3%A3o-em-asp-net-core-e-net-full-292f8b74cf1a
- https://medium.com/filipececcon/c-usando-dapper-com-fluentmap-linq-e-lambda-para-consultas-6f3131bff244
- https://www.treinaweb.com.br/blog/utilizando-o-micro-orm-dapper-em-uma-aplicacao-asp-net-core/
- https://docs.microsoft.com/pt-br/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1