ADO .NET - Usando o Micro ORM Dapper .net
Neste artigo vou apresentar os conceitos básicos sobre o Micro ORM Dapper mostrando como podemos usá-lo em aplicações feitas na plataforma .NET. |
Uma das operações comuns no desenvolvimento de um aplicativo de negócios é acessar dados usando um banco de dados relacional. Se você é um desenvolvedor .NET já deve saber que a plataforma .NET oferece muitas alternativas para realizar essa tarefa.
Podemos usar ADO .NET , LINQ to SQL , NHibernate e Entity Framework, apenas para citar as tecnologias de acesso a dados mais usadas na plataforma .NET.
Nos últimos anos a utilização de ferramentas ORM como o NHibernate e o Entity Framework têm crescido muito, afinal trabalhar com classes e objetos e abstrair os comandos SQL e os objetos da ADO .NET torna o trabalho mais simples, visto que a ferramenta ORM pode realizar o trabalho de mapeamento entre as tabelas e as entidades para nós de forma automática.
Infelizmente neste mundo nada é perfeito, e, usar uma ferramenta ORM sem conhecer muito bem o seu funcionamento pode camuflar problemas gravíssimos em uma aplicação mesmo que ele continue funcionando sem erros. (O problema Select + 1). Outro problema é que o código gerado pelo ORM pode ser muito complexo e difícil de otimizar.
Acresça a tudo isso o fato de que quando você usa uma ferramenta ORM você esta incluindo uma camada a mais na sua aplicação e isso vai afetar o seu desempenho de uma forma mais ou menos sensível dependendo de como você usou a ferramenta ORM. No caso do Entity Framework e o Linq to SQL ambos utilizam expressões LINQ causando sobrecarga no desempenho ao traduzir as instruções SQL nativas.
Neste cenário foi que surgiram os Micros ORM criados diretamente sobre ADO .NET e com uma proposta de aumentar o desempenho das iterações com o banco de dados relacionais. De forma bem simplificada, eles usam Reflection (dynamic a partir da versão 4.0 da plataforma .NET) para gerar objetos a partir do resultado da leitura dos dados.
Abaixo, a título de comparação, temos uma figura que compara o desempenho de consultas com diversas ferramentas para acesso a dados:
(fonte : https://github.com/StackExchange/dapper-dot-net )
Dessa forma, os Micros ORMs são ferramentas simples e que oferecem um ótimo desempenho no acesso a dados. Dentre os mais conhecidos temos:
Você pode acessar o link de cada um deles e ver mais detalhes.
Neste artigo eu vou mostrar como usar o Dapper .net que foi criado por Sam Saffron e disponibilizou o projeto como open source para toda a comunidade.
Recursos usados:
Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.
Usando o Dapper .net
Abra o VS Community e clique em New Project;
Selecione a linguagem Visual C# e o template Console Application;
Informe o nome da solução como Usando_Dapper e clique no botão OK;
Após criar o projeto vamos incluir a referência a biblioteca do Dapper .net e isso pode ser feito de duas formas:
Acessar diretamente o repositório do Dapper em https://github.com/StackExchange/dapper-dot-net . Ele é um arquivo único( ) que vai estender sua interface IDbConnection.
Instalar o Dapper no seu projeto usando o Nuget (creio que a opção mais simples)
No menu Tools clique no link para acessar o repositório Nuget e procure pelo pacote Dapper selecionando-o e clicando no botão Install:
Nota: Você pode instalar o pacote via Console usando o comando : Install-Package Dapper
Para mostrar como usar o Dapper vou usar o banco de dados Northwind.mdf e trabalhar com as tabelas Customers , Products e Suppliers.
Vamos armazenar a string de conexão com o banco de dados no arquivo App.Config :
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <connectionStrings> <add name="conexaoNorthwind" connectionString="Data Source=.\sqlexpress;Initial Catalog= Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> </configuration> |
Para acessar a string de conexão no arquivo App.Config vamos incluir uma referência ao namespace System.Configuration no projeto :
Agora já temos tudo pronto para mostrar como usar o Dapper.
Então vamos lá...
Defina o código abaixo que obtém a string de conexão do arquivo App.Config na classe Program:
static string strConexao = ConfigurationManager.ConnectionStrings["conexaoNorthwind"].ConnectionString;1- Acessando dados no SQL Server - Criando uma consulta simples para acessar a tabela Customers
private static void Exemplo1() { SqlConnection conexaoBD = new SqlConnection(strConexao); conexaoBD.Open(); var resultado = conexaoBD.Query("Select * from Customers"); Console.WriteLine("{0} - {1} - {2} ", "Código", "Nome do Contato", "Endereco do Cliente"); foreach (dynamic cliente in resultado) { Console.WriteLine("{0} - {1} - {2} ", cliente.CustomerID, cliente.ContactName, cliente.Address); } conexaoBD.Close(); } |
|
Observe que usamos o método de extensão Query(), existem muitos outros, e informamos o comando SQL e percorremos o resultado usando dynamic, pois não temos aqui uma classe como retorno, para exibir as informações desejadas:
Estamos retornando uma lista de objetos dinâmicos eliminando a necessidade de definir objeto DTO e simplificando o código.
Duas coisas importantes devem ser destacadas :
Todos os métodos de extensão do Dapper assumem que a conexão já esta aberta. Se a conexão estiver fechada o código vai falhar
Você é responsável por abrir e fechar as conexões
2- Retornado uma lista tipada de objetos
Vamos agora definir uma classe Produto e uma classe Fornecedor em nosso projeto com o código abaixo:
public class Produto { public int ProductId { get; set; } public string ProductName { get; set; } public int SupplierID { get; set; } public int CategoryID { get; set; } public string QuantityPerUnit { get; set; } public decimal UnitPrice { get; set; } public short? UnitsInStock { get; set; } public short? UnitsOnOrder { get; set; } public short? ReorderLevel { get; set; } public bool Discontinued { get; set; } // referencia public Fornecedor Fornecedor { get; set; } } |
public class Fornecedor { public int SupplierID { get; set; } public string CompanyName { get; set; } public string ContactName { get; set; } public string ContactTitle { get; set; } public string Address { get; set; } public string City { get; set; } public string PostalCode { get; set; } public string Country { get; set; } public IEnumerable<Produto> Produtos { get; set; } }
|
Agora vamos acessar a tabela Produtos e retornar uma lista selecionada de objetos tipados usando Dapper:
private static void Exemplo2() { using (var conexaoBD = new SqlConnection(strConexao)) { IEnumerable produtos = conexaoBD .Query<Produto>("Select * from Products"); Console.WriteLine("{0} - {1} - {2} ", "Código", "Nome do Produto", "Preço do Produto"); foreach (Produto produto in produtos) { Console.WriteLine("{0} - {1} - {2}", produto.ProductID, produto.ProductName, produto.UnitPrice); } } } |
|
Nesta consulta obtemos uma lista de objetos Produto (POCO). O Dapper usa os recursos do MSIL para acessar o data reader e converter os dados para o objeto de domínio.
3- Criando consultas com parâmetros
Agora vamos realizar uma consulta com parâmetros. É muito simples, basta definir a consulta com o parâmetro e depois passar um objeto anônimo com o valor desejado para o parâmetro.
private static void Exemplo3() { using (var conexaoBD = new SqlConnection(strConexao)) { IEnumerable produtos = conexaoBD .Query<Produto> ( "Select ProductID, ProductName, UnitPrice from Products Where UnitPrice > @Preco", new { Preco = 40 } ); Console.WriteLine("{0} - {1} - {2} ", "Código", "Nome do Produto", "Preço do Produto"); foreach (Produto produto in produtos) { Console.WriteLine("{0} - {1} - {2}", produto.ProductID, produto.ProductName, produto.UnitPrice); } } } |
|
No código acima temos a consulta filtrando pelo preço unitário : "Select ProductID, ProductName, UnitPrice from Products Where UnitPrice > @Preco"
Estamos definindo o parâmetro @Preco que a seguir criando um objeto anônimo passando o valor para o parâmetro: new { Preco = 40 }
4- Retornando múltiplos objetos com uma consulta
Agora vamos retornar múltiplos objetos com uma consulta. No exemplo definimos duas consultas SELECT para retornar o fornecedor com o código especificado e os respectivos produtos:
private static void Exemplo4() { using (var conexaoBD = new SqlConnection(strConexao)) { var consulta = @"SELECT * FROM dbo.Suppliers WHERE SupplierID = @Id SELECT * FROM dbo.Products WHERE SupplierID = @Id"; using (var resultado = conexaoBD .QueryMultiple(consulta, new { Id = 1 })) { var fornecedor = resultado.Read().Single(); var produtos = resultado.Read().ToList(); Console.WriteLine("Fornecedor - {0} ", fornecedor.CompanyName); Console.WriteLine(string.Format("Total de Produtos {0}", produtos.Count)); foreach (dynamic produto in produtos) { Console.WriteLine("{0} - {1} - {2}", produto.ProductID, produto.ProductName, produto.UnitPrice); } } } } |
|
Utilizamos o recurso QueryMultiple que suporta tratar com múltiplos conjuntos de resultados.
conexaoBD .QueryMultiple(consulta, new { Id = 1 }))
No exemplo definimos a consulta e passamos o valor para o parâmetro Id igual a 1.
5- Incluindo informações no banco de dados
Para incluir informações basta definir a consulta SQL Insert usando os valores e usar o método Execute():
private static void Exemplo5() { using (var conexaoBD = new SqlConnection(strConexao)) { var fornecedor = new Fornecedor() { Address = "Rua Projetada 100", CompanyName = "JcmSoft Inc." }; conexaoBD.Execute(@"insert Suppliers(CompanyName, Address) values (@CompanyName, @Address)", fornecedor); Console.WriteLine("Informações do fornecedor incluídas com sucesso."); } } |
6- Atualizando informações no banco de dados
A atualização de dados possui uma sintaxe parecida com a da inclusão. Aqui usamos uma instrução SQL Update com um objeto anônimo como parâmetro.
private static void Exemplo6() { using (var conexaoBD = new SqlConnection(strConexao)) { var atualizarBD = @"Update Products Set UnitPrice = @UnitPrice Where Id = @ProductId"; conexaoBD.Execute(atualizarBD, new { UnitPrice = 99.9m, ProductId = 50 }); Console.WriteLine("Informações do fornecedor incluídas com sucesso."); } } |
Neste artigo mostrei alguns dos recursos do Dapper .net usando os cenários mais comuns mas existem outros recursos que pretendo abordar nos próximos artigos.
Pegue o projeto completo aqui : Usando_Dapper.zip
Todavia digo-vos a verdade, que vos convém que eu vá; porque, se eu não for, o
Consolador não virá a vós; mas, quando eu for, vo-lo enviarei.
E, quando ele vier, convencerá o mundo do pecado, e da justiça e do juízo.
Do pecado, porque não crêem em mim;
Da justiça, porque vou para meu Pai, e não me vereis mais;
E do juízo, porque já o príncipe deste mundo está julgado.
João 16:7-11
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: