André Alves de Lima

Talking about Software Development and more…

Introdução ao Dapper

Não é de hoje que leitores do site pedem para que eu escreva sobre o Dapper, micro-ORM que tem a fama de ser extremamente performático e simples de utilizar. Eu relutei para escrever sobre essa biblioteca, principalmente porque até hoje eu não tive nenhuma experiência com ela, e eu só costumo escrever sobre alguma coisa quando eu tenho certeza do que eu estou falando (apesar que às vezes eu acabo falando algumas besteiras também – faz parte).

Porém, uma vez que o Dapper foi um dos tópicos mais votados na minha última pesquisa de temas para próximos artigos, aí não teve jeito. Resolvi me aprofundar nos estudos sobre essa biblioteca e, no artigo de hoje, vou apresentar para você uma “Introdução ao Dapper“, tomando como base os resultados dos meus aprendizados. Você se interessa por esse tema? Então vamos lá!

Disclaimer

Como mencionei na introdução do artigo, até a semana passada (que foi quando eu parei para estudar “de verdade” do Dapper), eu não tinha tido nenhuma experiência com ele. Eu apenas tinha lido “por cima” alguns artigos e assistido rapidamente alguns vídeos sobre essa biblioteca. Dessa forma, se eu acabar falando alguma besteira neste artigo, por favor, me corrija nos comentários, OK?

Aproveitando essa seção de “disclaimer“, quero deixar aqui uma lista com os recursos que eu utilizei para aprender o conteúdo que ensinarei neste artigo. A maioria deles foi elaborado pelo meu amigo Renato Groffe, que é Microsoft MVP e conhecido por ser uma “máquina de produzir conteúdo“, hehehe. Aqui vão os links:

Dapper: exemplos em .NET Core 2.0 e ASP.NET Core 2.0 (link)
Coletânea de artigos, exemplos e vídeos com participação do Renato Groffe onde ele aborda a utilização do Dapper. Recomendo que você dê uma olhada nos exemplos postados no GitHub dele, além de dar uma lida nos artigos mencionados, como, por exemplo, este artigo mostrando o conceito de relacionamentos no Dapper.

ORMs em .NET: Entity Framework, NHibernate e Dapper (link)
Hangout com participação do André Secco, Luiz Carlos Faria e Renato Groffe mostrando as particularidades do Entity Framework, NHibernate e Dapper. Recomendo que você assista para conseguir ter uma melhor base na hora de escolher um ORM ou micro-ORM (ou talvez até mesmo ADO.NET puro) para o seu projeto.

Acesso a dados em .NET Core: Entity Framework Core e Dapper (link)
Dos links que eu estou listando aqui, esse é o mais novo, que foi uma apresentação do André Secco na versão local do DotNetConf. Nesse vídeo o André Secco mostra a utilização do Entity Framework e do Dapper, bem como um cenário híbrido utilizando as duas tecnologias ao mesmo tempo (Entity Framework para CRUD e Dapper para consultas).

Entendendo o problema

Antes de mostrar a utilização do Dapper, é importante entendermos o problema que ele se propõe a resolver. Praticamente toda aplicação que nós construímos terá algum tipo de armazenamento de informações no banco de dados. Normalmente, a estrutura do banco de dados refletirá de certa forma a estrutura de classes da nossa aplicação (ou vice-versa).

Quando implementamos a interface com o banco de dados no nosso projeto .NET, nós temos basicamente três opções: ou trabalhamos com ADO.NET puro (fazendo todas as consultas “na mão“), ou utilizamos um ORM (como Entity Framework ou NHibernate) ou um micro-ORM (como o Dapper). Os ORMs atuam como uma camada entre as classes da aplicação e o ADO.NET, de maneira que nós não precisemos praticamente escrever nenhuma sentença SQL para nos comunicarmos com o banco. Eles possibilitam o mapeamento das classes do nosso projeto com as tabelas no banco de dados (daí o nome ORM = “Object-Relational Mapping“).

Quanto mais produtiva é a abordagem que nós escolhemos (ORMs), menos performática ela será. Por consequência, se precisarmos de uma performance absurda na nossa aplicação, nós provavelmente não poderemos trabalhar com ORMs, mas sim, com ADO.NET puro.

A ideia dos micro-ORMs é justamente dar uma opção intermediária entre produtividade e performance. Eles trazem parte das funcionalidades de mapeamento objeto-relacional dos ORMs, mas sem implementar a cacetada de funcionalidades (muitas vezes pouco utilizadas) que acabam os deixando mais lentos.

Projeto de exemplo sem Dapper

Para estudarmos a utilização do Dapper no acesso a dados, vamos trabalhar com um projeto do tipo “Console Application“. Essa aplicação criará registros em uma tabela chamada “Pessoa” dentro de um banco SQLite. Para focarmos no que é importante, vamos manter a estrutura dessa tabela extremamente simples, contendo somente os campos “Id” (chave primária, auto-incremento), “Nome” e “Sobrenome“:

Nota: baixe o banco de dados vazio (que tem somente essa tabela criada) através deste link e coloque-o dentro da pasta bin/debug do seu projeto.

Dentro do nosso projeto, vamos adicionar a classe correspondente, que também terá o nome de “Pessoa“:

    // C#
    public class Pessoa
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
    }
' VB.NET
Public Class Pessoa
    Public Property Id As Integer
    Public Property Nome As String
    Public Property Sobrenome As String
End Class

Em seguida, vamos adicionar uma referência para a biblioteca de acesso a dados do SQLite através do NuGet:

Nota: uns tempos atrás eu escrevi um artigo completo mostrando como trabalhar com o SQLite utilizando ADO.NET puro e Entity Framework. Se você não entender o que estou fazendo aqui neste artigo até agora, sugiro que você dê uma olhada primeiro no artigo básico sobre SQLite.

Como mencionei acima, essa aplicação basicamente fará o cadastro de novas pessoas nessa tabela, bem como a listagem das pessoas que estão cadastradas. Dito isso, o código do método “main” deverá ter esta estrutura:

        // C#
        static void Main(string[] args)
        {
           string nome = string.Empty;
            do
            {
                Console.WriteLine("Digite o nome:");
                nome = Console.ReadLine();
                if (!string.IsNullOrWhiteSpace(nome))
                {
                    Console.WriteLine("Digite o sobrenome:");
                    var sobrenome = Console.ReadLine();
                    if (!string.IsNullOrWhiteSpace(sobrenome))
                    {
                        var pessoa = new Pessoa()
                        {
                            Nome = nome,
                            Sobrenome = sobrenome
                        };
                        CadastrarPessoaNoBanco(pessoa);
                    }
                }

                ListarPessoas();
            }
            while (!string.IsNullOrWhiteSpace(nome));

            Console.ReadLine();
        }
    ' VB.NET
    Sub Main()
        Dim Nome As String = String.Empty
        Do
            Console.WriteLine("Digite o nome:")
            Nome = Console.ReadLine()
            If Not String.IsNullOrWhiteSpace(Nome) Then
                Console.WriteLine("Digite o sobrenome:")
                Dim Sobrenome = Console.ReadLine()
                If Not String.IsNullOrWhiteSpace(Sobrenome) Then
                    Dim Pessoa = New Pessoa() With
                    {
                        .Nome = Nome,
                        .Sobrenome = Sobrenome
                    }
                    CadastrarPessoaNoBanco(Pessoa)
                End If
            End If

            ListarPessoas()
        Loop While Not String.IsNullOrWhiteSpace(Nome)

        Console.ReadLine()
    End Sub

Observe que nós estamos pedindo as informações de nome e sobrenome para o usuário e, em seguida, criamos uma instância da classe “Pessoa” que será passada para o método “CadastrarPessoaNoBanco“. Por fim, nós chamamos o método “ListarPessoas“, que carregará os dados da tabela “Pessoa” em memória e imprimirá o resultado na tela. Todo esse processo será executado enquanto o usuário informar um nome que seja diferente de “vazio“.

O código do método “CadastrarPessoaNoBanco” com a utilização do ADO.NET puro é muito simples. Instanciamos uma conexão com o banco, abrimos essa conexão, criamos um comando com a sentença SQL “INSERT” e passamos os valores através de parâmetros do ADO.NET. Por fim, chamamos o método “ExecuteNonQuery” para persistirmos as informações no banco:

        // C#
        private static void CadastrarPessoaNoBanco(Pessoa pessoa)
        {
            using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;"))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    using (var comm = new System.Data.SQLite.SQLiteCommand("INSERT INTO Pessoa (Nome, Sobrenome) VALUES (@Nome, @Sobrenome)", conn))
                    {
                        comm.Parameters.AddWithValue("Nome", pessoa.Nome);
                        comm.Parameters.AddWithValue("Sobrenome", pessoa.Sobrenome);
                        comm.ExecuteNonQuery();
                    }
                }
            }
        }
    ' VB.NET
    Private Sub CadastrarPessoaNoBanco(pessoa As Pessoa)
        Using Conn = New System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;")
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Using Comm = New System.Data.SQLite.SQLiteCommand("INSERT INTO Pessoa (Nome, Sobrenome) VALUES (@Nome, @Sobrenome)", Conn)
                    Comm.Parameters.AddWithValue("Nome", pessoa.Nome)
                    Comm.Parameters.AddWithValue("Sobrenome", pessoa.Sobrenome)
                    Comm.ExecuteNonQuery()
                End Using
            End If
        End Using
    End Sub

Nota: se você não utiliza a funcionalidade de parâmetros do ADO.NET, mas sim concatena os valores direto na sentença SQL, pare agora mesmo e leia este outro artigo! Sério, é super importante!

Por sua vez, o código do método “ListarPessoas” também é bem simples. Nós executaremos um “SELECT” no banco pegando todos os registros da tabela “Pessoa” (utilizando DataReader) e colocaremos o resultado em uma lista. Em seguida, nós percorremos essa lista e imprimimos as informações das pessoas na tela:

        // C#
        private static void ListarPessoas()
        {
            Console.WriteLine("======= Listagem de pessoas =======");

            var pessoas = CarregarPessoasDoBanco();
            foreach (var pessoa in pessoas)
            {
                Console.WriteLine("Id: {0}, Nome: {1}, Sobrenome: {2}", pessoa.Id, pessoa.Nome, pessoa.Sobrenome);
            }

            Console.WriteLine("===================================");
        }
        private static IEnumerable<Pessoa> CarregarPessoasDoBanco()
        {
            var pessoas = new List<Pessoa>();

            using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;"))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    using (var comm = new System.Data.SQLite.SQLiteCommand("SELECT * FROM Pessoa", conn))
                    using (var reader = comm.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var pessoa = new Pessoa();
                            pessoa.Id = Convert.ToInt32(reader["Id"]);
                            pessoa.Nome = reader["Nome"].ToString();
                            pessoa.Sobrenome = reader["Sobrenome"].ToString();
                            pessoas.Add(pessoa);
                        }
                    }
                }
            }

            return pessoas;
        }
    ' VB.NET
    Private Sub ListarPessoas()
        Console.WriteLine("======= Listagem de pessoas =======")

        Dim Pessoas = CarregarPessoasDoBanco()
        For Each Pessoa In Pessoas
            Console.WriteLine("Id: {0}, Nome: {1}, Sobrenome: {2}", Pessoa.Id, Pessoa.Nome, Pessoa.Sobrenome)
        Next

        Console.WriteLine("===================================")
    End Sub
    Private Function CarregarPessoasDoBanco() As IEnumerable(Of Pessoa)
        Dim Pessoas = New List(Of Pessoa)()

        Using Conn = New System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;")
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Using Comm = New System.Data.SQLite.SQLiteCommand("SELECT * FROM Pessoa", Conn)
                    Using Reader = Comm.ExecuteReader()
                        While Reader.Read()
                            Dim Pessoa = New Pessoa()
                            Pessoa.Id = Convert.ToInt32(Reader("Id"))
                            Pessoa.Nome = Reader("Nome").ToString()
                            Pessoa.Sobrenome = Reader("Sobrenome").ToString()
                            Pessoas.Add(Pessoa)
                        End While
                    End Using
                End Using
            End If
        End Using

        Return Pessoas
    End Function

Pronto! Esse é o código da nossa aplicação utilizando ADO.NET puro, sem Dapper, sem Entity Framework, o mais simples e performático possível. Execute a aplicação, crie algumas pessoas e veja o resultado:

Qual é exatamente o problema dessa implementação? Como o Dapper poderia deixar esse nosso código mais simples? Isso é o que veremos agora.

Instalando o Dapper

Primeiramente, a instalação do Dapper é muito tranquila. Basta adicionarmos a referência através do NuGet:

Feito isso, para termos acesso aos métodos de extensão disponibilizados pelo Dapper, nós precisamos adicionar uma cláusula “using Dapper;” (ou “Imports Dapper” no VB.NET) no cabeçalho do arquivo onde faremos a sua utilização (no nosso caso, o arquivo “Program.cs” ou “Module1.vb“). Não esqueça desse passo, caso contrário você não conseguirá encontrar os métodos especiais do Dapper.

Mapeando resultados de uma consulta com o Dapper

O Dapper pode nos ajudar no mapeamento dos resultados do banco em instâncias das nossas classes de modelo. Ou seja, ao invés de pegarmos as informações através de um DataReader e criarmos manualmente as instâncias da classe “Pessoa“, nós podemos utilizar o Dapper para fazer esse trabalho “sujo“.

Veja só como é que fica o novo código do método “CarregarPessoasDoBanco” com a utilização do Dapper:

        // C#
        private static IEnumerable<Pessoa> CarregarPessoasDoBanco()
        {
            IEnumerable<Pessoa> pessoas = null;

            using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;"))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    pessoas = conn.Query<Pessoa>("SELECT * FROM Pessoa");
                }
            }

            return pessoas;
        }
    ' VB.NET
    Private Function CarregarPessoasDoBanco() As IEnumerable(Of Pessoa)
        Dim Pessoas As IEnumerable(Of Pessoa) = Nothing

        Using Conn = New System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;")
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Pessoas = Conn.Query(Of Pessoa)("SELECT * FROM Pessoa")
            End If
        End Using

        Return Pessoas
    End Function

Observe que agora estamos utilizando o método “Query” do Dapper. Esse método recebe o tipo de dados que deverá ser gerado (no nosso caso “Pessoa“) e a sentença que será utilizada para preencher os resultados. Por trás dos panos, o Dapper executa aquela sentença, cria instâncias do tipo especificado e retorna um “IEnumerable” daquele tipo. Bem mais simples, não é mesmo?

Executando comandos parametrizados com o Dapper

Uma outra funcionalidade bem bacana que o Dapper disponibiliza são as consultas parametrizadas com objetos anônimos. Lembra o código do método “CadastrarPessoaNoBanco” que vimos ali em cima? Naquele código nós tivemos que criar um comando, adicionar cada um dos parâmetros e, por fim, chamamos o método “ExecuteNonQuery” para que o comando fosse executado. Com o Dapper, esse código fica muito mais enxuto:

        // C#
        private static void CadastrarPessoaNoBanco(Pessoa pessoa)
        {
            using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;"))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    conn.Execute(
                        "INSERT INTO Pessoa (Nome, Sobrenome) VALUES (@Nome, @Sobrenome)",
                        new { Nome = pessoa.Nome, Sobrenome = pessoa.Sobrenome });
                }
            }
        }
    ' VB.NET
    Private Sub CadastrarPessoaNoBanco(pessoa As Pessoa)
        Using Conn = New System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;")
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Conn.Execute("INSERT INTO Pessoa (Nome, Sobrenome) VALUES (@Nome, @Sobrenome)", New With
                {
                    .Nome = pessoa.Nome,
                    .Sobrenome = pessoa.Sobrenome
                })
            End If
        End Using
    End Sub

Como você pode perceber, o método “Execute” implementado pelo Dapper possibilita que nós passemos os parâmetros através de um objeto anônimo (que são aqueles objetos criados com a palavra reservada “new“). Ou seja, nós informamos os nomes dos parâmetros na sentença SQL (precedidos de arroba) e depois passamos os valores através de um objeto anônimo. Muito bacana!

Implementando CRUD com Dapper.Contrib

As melhorias proporcionadas pelo Dapper que vimos até agora já dão uma bela ajudada na hora de carregarmos informações do banco com ADO.NET puro. Porém, dá para ficar ainda melhor! Com uma extensão do Dapper chamada “Dapper.Contrib“, as nossas operações de criação, alteração e deleção de registros ficarão mais fáceis ainda.

Primeiramente, vamos adicionar a referência para essa biblioteca através do NuGet:

Em seguida, precisamos adicionar uma cláusula “using Dapper.Contrib.Extensions;” (ou “Imports Dapper.Contrib.Extensions” no VB.NET) no cabeçalho do arquivo onde queremos acessar as suas funcionalidades (no nosso caso, o arquivo “Program.cs” ou “Module1.vb“).

Feito isso, teremos acesso aos métodos de extensão do “Dapper.Contrib“, que basicamente nos ajudam a implementar as funcionalidades de CRUD mais facilmente (os principais métodos são “Get“, “GetAll“, “Insert“, “Update“, “Delete” e “DeleteAll“).

Por exemplo, no nosso método “CarregarPessoasDoBanco“, nós não precisamos mais utilizar uma sentença SQL para pegarmos todos os registros da tabela “Pessoa” do banco. Basta utilizarmos o método “GetAll” do “Dapper.Contrib“:

// C#
pessoas = conn.GetAll<Pessoa>();
' VB.NET
Pessoas = Conn.GetAll(Of Pessoa)()

Além disso, no método “CadastrarPessoasNoBanco“, nós não precisamos mais construir uma sentença SQL para inserirmos uma nova pessoa no banco. Com o método “Insert” do “Dapper.Contrib” nós podemos passar a instância da classe “Pessoa” que deve ser inserida no banco e ele fará todo o trabalho por trás dos panos:

        // C#
        private static void CadastrarPessoaNoBanco(Pessoa pessoa)
        {
            using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;"))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    conn.Insert(pessoa);
                }
            }
        }
    ' VB.NET
    Private Sub CadastrarPessoaNoBanco(pessoa As Pessoa)
        Using Conn = New System.Data.SQLite.SQLiteConnection("Data Source=db.db;Version=3;")
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Conn.Insert(pessoa)
            End If
        End Using
    End Sub

Porém, se executarmos esse novo código, nós receberemos o seguinte erro:

Esse erro ocorre porque o “Dapper.Contrib” considera por padrão que todas as tabelas estão pluralizadas. Ou seja, como a nossa classe se chama “Pessoa“, o “Dapper.Contrib” acha que as informações estarão armazenadas na tabela “Pessoas“, e isso não é verdade no nosso caso.

Nós temos duas opções para corrigirmos esse erro. A primeira opção é definirmos o nome da tabela na nossa classe “Pessoa” através de data annotations:

Porém, muita gente não gosta de poluir as classes de modelo com data annotations. Nesse caso, uma outra opção que temos à nossa disposição é a utilização do evento “SqlMapperExtensions.TableNameMapper“. Se colocarmos esse código no começo do nosso método “main“, o “Dapper.Contrib” considerará que as tabelas têm o mesmo nome das classes de modelo:

            // C#
            SqlMapperExtensions.TableNameMapper += (type) =>
            {
                return type.Name;
            };
        ' VB.NET
        SqlMapperExtensions.TableNameMapper = New SqlMapperExtensions.TableNameMapperDelegate(Function(type As Type)
                                                                                                  Return type.Name
                                                                                              End Function)

E com esse ajuste o nosso projeto funcionará corretamente, salvando e carregando as informações da tabela “Pessoa“.

Operações mais avançadas

Como este artigo já está ficando muito longo, vou deixar algumas operações mais avançadas para outros artigos futuros. Veja aqui uma lista com possíveis temas para outros artigos sobre Dapper:

– Como carregar dados de mais de uma tabela ao mesmo tempo?
– Como trabalhar com relacionamentos entre tabelas?
– E se os campos da minha classe de dados não tiverem os mesmos nomes das colunas no banco?

Baixe o projeto de exemplo

Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.

Concluindo

Micro-ORMs como o Dapper têm o objetivo de simplificar um pouco o processo maçante de leitura de dados quando trabalhamos com ADO.NET puro nos nossos projetos. Apesar de fazer o mapeamento objeto-relacional, ele procura manter as suas funcionalidades muito enxutas, a fim de não prejudicar muito a performance, ao contrário do que costumam fazer os ORMs “completos” como Entity Framework e NHibernate.

No artigo de hoje você viu uma introdução ao Dapper, onde você primeiramente aprendeu a instalá-lo e, em seguida, aprendeu a aplicar os seus métodos para simplificar os códigos de consulta e execução de sentenças SQL. Por fim, vimos a utilização de uma extensão do Dapper, chamada “Dapper.Contrib“, que implementa métodos que facilitam as operações de CRUD no nosso projeto.

E você, utiliza algum ORM nos seus projetos? Está contente com a sua performance ou está pensando em partir para um micro-ORM? Ou talvez você nem sabia da existência do Dapper ou nem sabia a fundo como o Dapper funcionava (como eu) e agora está pensando em utilizá-lo nos seus projetos também? Fico aguardando os seus comentários logo abaixo!

Até a próxima!

André Lima

Image by Pixabay used under Creative Commons
https://pixabay.com/en/network-rectangle-board-rings-1989141/

Newsletter do André Lima

* indicates required



Powered by MailChimp

22 thoughts on “Introdução ao Dapper

  • Anderson disse:

    André, achei muito bacana seu artigo, não conhecia o Dapper, achei muito interessante, vou me aprofundar no assunto para utilizar nos meus projetos!
    Fico no aguardo dos artigos mais avançados!

    Só fiquei com uma dúvida, nos exemplos, você só cria o obejto de conexão com o banco:
    var conn = new System.Data.SQLite.SQLiteConnection(“Data Source=db.db;Version=3;”)

    E depois só utiliza os métodos:
    conn.Insert(pessoa);
    conn.Execute(…)
    pessoas = conn.Query(“SELECT * FROM Pessoa”);

    Esse objeto conn não seria o objeto do SQLite? Não deveria ter um objeto do Dapper?

    Obrigado!

    • andrealveslima disse:

      Olá Anderson!

      Sim, o objeto é do tipo SQLiteConnection, porém, o que o Dapper faz é adicionar métodos de extensão à classe DbConnection (que é a classe “pai” de todas as classes de conexão do ADO.NET, inclusive a SQLiteConnection).. Você conhece o conceito de métodos de extensão? Basicamente é uma maneira de adicionar métodos a uma classe já existente.. Por exemplo, você pode criar o seu próprio método de extensão para a classe “string”, de forma que você consiga chamá-lo em qualquer instância desse tipo:

      string suaString = "XYZ";
      suaString.SeuMetodoDeExtensao();
      

      Basicamente é isso que o Dapper faz.. Adiciona métodos utilitários à classe DbConnection.. Leia mais sobre o conceito de métodos de extensão na documentação do MSDN:

      Métodos de extensão (Guia de Programação em C#)

      Abraço!
      André Lima

  • Fausto Luís disse:

    Olá, André.

    Gostei muito do seu artigo. Está ótimo para iniciantes, de certeza que ficarão com “agua na boca”, como se diz aqui em Portugal.

    Como falou que vai publicar artigos com conteúdo mais avançado, pus-me a pensar se não irá introduzir o conceito de “Data Repositories”; caso isso aconteça, dê uma olhada neste artigo, a mim deu-me muito jeito no meu processo de aprendizagem: http://www.bradoncode.com/blog/2012/12/creating-data-repository-using-dapper.html. Já é um pouco antigo, mas mesmo assim…achei muito bom.

    Abraço,
    Fausto

  • Renato Groffe disse:

    André, parabéns pelo conteúdo direto e abrangente! E obrigado por mencionar meu material também!

    • andrealveslima disse:

      Fala Renato!

      Muito obrigado pelo comentário! Eu que agradeço pelas suas postagens sobre o Dapper.. Elas foram essenciais no meu aprendizado sobre essa biblioteca.. :)

      Abraço!
      André Lima

  • claudio disse:

    muito bom…parabéns
    teremos mais xamarin?

    • andrealveslima disse:

      Olá Claudio, muito obrigado pelo comentário!

      Sim! Teremos mais Xamarin.. Estou tentando escrever mais ou menos um artigo por mês sobre Xamarin.. O próximo deve sair daqui umas duas ou três semanas..

      Abraço!
      André Lima

  • João Vitor disse:

    Parabéns pelo artigo , conheci seu site a pouco tempo e fiquei muito impressionado , a tempos que procuro um site sobre Net que poste coisas regularmente e tenha um conteúdo abrangente e consistente!.
    Continue assim!

    • andrealveslima disse:

      Olá João Vitor, muito obrigado pelo comentário!

      Fico muito feliz por estar conseguindo te ajudar com as minhas publicações.. Se algum dia você tiver alguma sugestão de outros assuntos que eu possa abordar aqui no site, é só entrar em contato..

      Abraço!
      André Lima

  • Alex Alves Moraes disse:

    Parabéns André, muito bom artigo como sempre, não conhecia o Dapper, e fiquei super interessado em aprender mais, vou me aprofundar no assunto para utilizar nos meus projetos!

    Eu voto por nos próximos artigos de Dapper seja sobre:
    – Como trabalhar com relacionamentos entre tabelas?
    – E se os campos da minha classe de dados não tiverem os mesmos nomes das colunas no banco?

    Uma duvida, eu conseguiria fazer um mapeamento personalizado?

    por exemplo: No caso que você deu, quero listar quantas pessoas tem o mesmo nome, então faço a seguinte Query: “SELECT Nome, count(*) as Qtd_Nome_Repetido FROM pessoa group by Nome”.

    Neste caso eu teria que criar uma class com os campo Nome e Qtd só para poder retornar para aplicação?

    • andrealveslima disse:

      Olá Alex, muito obrigado pelo comentário!

      Quanto à sua questão de mapeamento personalizado, nesse caso se você utilizar o método “Query” não genérico do Dapper, ele retorna objetos do tipo dynamic, que você pode acessar as propriedades tranquilamente depois.. O único problema é que, como são objetos do tipo dynamic, você não tem checagem em tempo de compilação, aí se você acessar alguma propriedade que não existe no retorno, você só vai receber o erro em tempo de execução..

      Se você der uma olhada nesta thread do StackOverflow, você verá um exemplo disso que eu acabei de explicar, além de uma alternativa para se trabalhar com objetos anônimos com o Dapper, que, esses sim, teriam checagem em tempo de compilação..

      Abraço!
      André Lima

  • deuzivaldo disse:

    Parabéns professor só você mesmo para nos ajudarmos obrigado

  • […] um meio termo, que são os micro-ORMs. Caso você se interesse por esse meio termo, confira o meu artigo sobre Dapper, que é o micro-ORM para .NET mais conhecido […]

  • Alexandre disse:

    Alguém conseguiu fazer download do projeto inscrevendo-se na newsletter?

    • andrealveslima disse:

      Olá Alexandre!

      O link para baixar os projetos de exemplo é enviado junto ao e-mail de confirmação de inscrição.. De qualquer forma, eu acabei de te enviar um e-mail novamente com o link.. Qualquer coisa é só falar..

      Abraço!
      André Lima

  • Robson disse:

    André muito bacana o seu tópico, e inclusive eu estou com o seguinte problema, eu tenho uma aplicação web, utilizo o dot.net, essa aplicação permite que o usuário busque uma determinada planilha de Excel, e nessa planilha contém mais de 6 mil registro relacionado a processos jurídicos, só que quando o usuário seleciona o arquivo e clica no botão importar, o sistema fica lento, ao invés de ter um desempenho e uma performance melhor, acaba que fica ocorrendo essa lentidão.Utilizo o visual studio 2010, é possivel aplicar o Dapper no meu projeto? Você tem alguma sugestão para acrescentar em melhorias, em código para o meu projeto web?

    Segue o meu código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Text;
    using SDPJDominio.APL;
    using System.Data;
    using SDPJDominio.Domain;
    using System.IO;
    using System.Globalization;
    using SDPJView.Content.AuxiliarCPF_CNPJ;
    using SDPJView.Content.Seguranca;
    using SDPJView.Content;
    using SDPJView.Content.Resource;

    namespace SDPJView.ImportacaoProcessoView
    {
    public partial class ImportacaoProcesso : PageBase
    {
    public bool arquivoInvalidado = false;
    public StringBuilder log = new StringBuilder();
    public StringBuilder logErro = new StringBuilder();
    public AplUsuario aplUsuario = new AplUsuario();
    public AplProcesso aplProcesso = new AplProcesso();
    public AplLogAtividade aplLog = new AplLogAtividade();
    public AplInteressado aplInteressado = new AplInteressado();
    public AplProcessoInteressado aplProcessoInteressado = new AplProcessoInteressado();
    public AplVaraExecucao aplVaraExecucao = new AplVaraExecucao();
    public List listaGravarProcesso = new List();
    public List listaInteressadoArq = new List();
    public List listaProcessoInteressado = new List();
    public List listaGravarProcInter = new List();
    public List listaLogsAuditoria = new List();
    public List listaMunicipios
    {
    get { return (List)ViewState[“listaMunicipios”]; }
    set { ViewState[“listaMunicipios”] = value; }
    }
    //public bool interessadoIgual = false;

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!Page.IsPostBack)
    {
    ValidaSessao();
    ValidaFuncao(“PROC_IP005”);

    //ScriptManager.GetCurrent(Page).RegisterPostBackControl(importar);

    this.Title = “SDPJ::Importação de Processos”;
    logimportacao.Visible = false;
    this.listaMunicipios = new AplMunicipio().listaTodos();
    }
    }

    protected void importar_Click(object sender, EventArgs e)
    {
    //Verifica se um arquivo foi selecionado
    if (selecionarArquivo.HasFile)
    {
    //Valida a extensão do arquivo:
    if (Path.GetExtension(selecionarArquivo.FileName) != “.xlsx” && Path.GetExtension(selecionarArquivo.FileName) != “.xls”)
    ClientScript.RegisterStartupScript(typeof(string), “Erro”, “alert(‘Somente arquivos em excel’)”);

    else
    {
    if (selecionarArquivo.FileContent != null)
    {
    string Excel = AppDomain.CurrentDomain.BaseDirectory + selecionarArquivo.FileName;
    selecionarArquivo.SaveAs(Excel);
    DataTable Dados = DadosExcel(Excel);
    DataSet ds = new DataSet();

    ds.Tables.Add(Dados);

    if (ds.Tables.Count > 0)
    {
    bool layoutValido = VerificaLayout(ds);
    if (!layoutValido)
    ClientScript.RegisterStartupScript(typeof(string), “Erro”, “alert(‘Layout do arquivo fora do padrão definido para importação.’)”);
    else
    {
    //Inicio da validação dos dados inseridos na planilha
    int numLinhas = ds.Tables[0].Rows.Count;
    //Validação básica necessária para importação. PS: NumLinhas-1 porque o arquivo tem a última linha com total, que é inútil à importação.
    VerificacaoPreliminar((numLinhas – 1), ds);

    //Inicio da rotina de repetição para leitura de todas as linhas, iniciando na célula B6
    if (!arquivoInvalidado)
    {

    //ClientScript.RegisterStartupScript(Page.GetType(), “Carregando…”, “document.getElementById(‘progresso’).style.width = ‘30%’;”);
    //Verifica se existe mais de 1 interessado com mesmo CPF cadastrado, salva os interessados inexistentes e altera os cadastros q tem interessados duplicados.
    this.ValidaDuplicidadeInteressado();

    for (int i = 5; i < (numLinhas – 1); i++)
    {
    List listaProcessoExistente = new List();
    Processo processo = null;
    Interessado interessado = new Interessado();

    //busca o processo pelo nº judicial anterior ou atual
    if (!ds.Tables[0].Rows[i].ItemArray[1].ToString().Equals(“”))
    processo = aplProcesso.consultarPorNProcessoER(ds.Tables[0].Rows[i].ItemArray[1].ToString());
    if (processo == null)
    {
    if (!ds.Tables[0].Rows[i].ItemArray[2].ToString().Equals(“”))
    processo = aplProcesso.consultarPorNProcessoER(ds.Tables[0].Rows[i].ItemArray[2].ToString());
    }
    //busca o interessado por cpf/cnpj
    if (ds.Tables[0].Rows[i].ItemArray[7].ToString().Length == 14)
    interessado = aplInteressado.ConsultarPorCPF(AuxiliarCPF_CNPJ.DesformataCPF(ds.Tables[0].Rows[i].ItemArray[7].ToString()));
    if (ds.Tables[0].Rows[i].ItemArray[7].ToString().Length == 18)
    interessado = aplInteressado.ConsultarPorCPF(AuxiliarCPF_CNPJ.DesformataCNPJ(ds.Tables[0].Rows[i].ItemArray[7].ToString()));
    if (processo != null)
    {
    //se o processo não for nulo busco todos procinter relacionados a ele
    List listaprocinter = aplProcessoInteressado.consultarPorIdProcesso(processo.Codigo);
    if(listaprocinter.Exists(o=>o.Interessado == interessado))
    log.Append(“O interessado informado na linha ” + (i + 1) + ” foi adicionado novamente ao processo ” + processo.NumProcessoJudicial + ” “);
    //foreach(var item in listaprocinter)
    //{
    // if (item.Interessado == interessado)
    // log.Append(“O interessado informado na linha ” + (i + 1) + ” foi adicionado novamente ao processo ” + processo.NumProcessoJudicial + ” “);
    //}
    setProcInter(processo, interessado, ds, i);
    }
    else
    {
    //Novo Processo – 6.3
    processo = new Processo();

    processo.Interessado = interessado;

    processo.NumProcessoJudicial = ds.Tables[0].Rows[i].ItemArray[2].ToString().Trim();
    processo.RenunciaCredito = “N”;
    processo.Situacao = new AplSituacao().ConsultarPorId(1);
    processo.HonorarioDativo = “S”;
    processo.Reclamado = new AplReclamado().buscaItem(2);
    processo.TipoDocumento = new AplTipoDocumento().buscaItem(4);
    processo.TipoProcesso = “O”;
    if (ds.Tables[0].Rows[i].ItemArray[5].ToString().Contains(“juizado”))
    processo.Tribunal = new AplTribunal().buscaItem(71);
    else
    processo.Tribunal = new AplTribunal().buscaItem(3);
    processo.NaturezaDespeza = new AplNaturezadeDespesa().buscaItem(3);

    VaraExecucao vara = new VaraExecucao();
    if (!ds.Tables[0].Rows[i].ItemArray[3].ToString().Equals(“”) && !ds.Tables[0].Rows[i].ItemArray[5].ToString().Equals(“”))
    {
    List listaVaraComarca = aplVaraExecucao.ConsultarPorNomeVaraNomeComarca(ds.Tables[0].Rows[i].ItemArray[5].ToString().Trim(), ds.Tables[0].Rows[i].ItemArray[3].ToString().Trim());
    if (listaVaraComarca.Count != 0)
    {

    if (ds.Tables[0].Rows[i].ItemArray[4].ToString().Equals(“”))
    {
    vara = listaVaraComarca.Find(o => o.NumeroVara == null);
    }
    else
    {
    vara = listaVaraComarca.Find(o => o.NumeroVara == int.Parse(ds.Tables[0].Rows[i].ItemArray[4].ToString().Trim()));
    }
    }
    }
    if (vara != null && vara.Codigo != 0)
    {
    processo.VaraExecucao = vara;
    }
    aplProcesso.gravar(processo);
    aplLog.LogarAtividade(aplUsuario.buscaPorLogin(ObterUsuarioAutenticado().Login), “Importação do processo de número judicial: ” + processo.NumProcessoJudicial
    + “. Interessado: ” + processo.Interessado.Nome + ” – ” + processo.Interessado.CPF_CNPJ + “. Tribunal ”
    + processo.Tribunal.NomeTribunal + “.”, DateTime.Now);
    //log.Append(“O processo ” + processo.NumProcessoJudicial + ” informado na linha ” + (i + 1) + ” foi cadastrado com sucesso. “);

    setProcInter(processo, interessado, ds, i);
    }
    }//Fim For
    //ClientScript.RegisterStartupScript(typeof(string), “Carregando…”, “$(‘#progressbar’).progressbar({value: 70});”);
    ClientScript.RegisterStartupScript(Page.GetType(), “Carregando…”, “document.getElementById(‘progresso’).style.width = ‘60%’;”);

    if (listaGravarProcInter.Count != 0)
    {
    foreach (ProcessoInteressado item in listaGravarProcInter)
    {
    aplProcessoInteressado.salvar(item);
    }
    }
    if (listaLogsAuditoria.Count != 0)
    {
    foreach (var item in listaLogsAuditoria)
    {
    aplLog.LogarAtividade(aplUsuario.buscaPorLogin(ObterUsuarioAutenticado().Login), item, DateTime.Now);
    }
    }
    logimportacao.Visible = true;
    loglbl.Text = log.ToString();
    //ClientScript.RegisterStartupScript(Page.GetType(), “Carregando…”, “document.getElementById(‘progresso’).style.width = ‘100%’;”);
    ClientScript.RegisterStartupScript(typeof(string), “Alerta”, “alert(‘Arquivo importado com sucesso. Verifique o log na tela. ‘)”);
    }
    else
    {
    logimportacao.Visible = true;
    loglbl.Text = log.ToString();
    ClientScript.RegisterStartupScript(typeof(string), “Erro”, “alert(‘Arquivo não importado. Verifique o log de erros na tela. ‘)”);
    }

    }
    }
    }
    }
    }
    }

    private Interessado setInteressado(DataSet ds, int linha)
    {
    Interessado interessado = new Interessado();
    AplMunicipio aplMunicipio = new AplMunicipio();
    AplBairro aplBairro = new AplBairro();

    interessado.Nome = ds.Tables[0].Rows[linha].ItemArray[6].ToString().ToUpper();
    if (!ds.Tables[0].Rows[linha].ItemArray[8].ToString().Equals(“”))
    interessado.Endereco = ds.Tables[0].Rows[linha].ItemArray[8].ToString().ToUpper();
    if (!ds.Tables[0].Rows[linha].ItemArray[9].ToString().Equals(“”))
    interessado.Numero = interessado.Complemento = ds.Tables[0].Rows[linha].ItemArray[9].ToString();
    if (!ds.Tables[0].Rows[linha].ItemArray[10].ToString().Equals(“”))
    interessado.Complemento = ds.Tables[0].Rows[linha].ItemArray[10].ToString().ToUpper();
    if (!ds.Tables[0].Rows[linha].ItemArray[13].ToString().Equals(“”))
    {
    //Municipio municipio = aplMunicipio.ConsultarPorNome(ds.Tables[0].Rows[linha].ItemArray[13].ToString().ToUpper());
    Municipio municipio = this.listaMunicipios.Find(m => Utilitarios.RemoveAcentos(m.Nome).ToUpper() == Utilitarios.RemoveAcentos(ds.Tables[0].Rows[linha].ItemArray[13].ToString()).ToUpper());
    if (municipio == null)
    {
    municipio = new Municipio();
    municipio.Estado = new AplEstado().buscaItem(1);
    municipio.Nome = ds.Tables[0].Rows[linha].ItemArray[13].ToString().ToUpper();
    aplMunicipio.gravar(municipio);
    }

    interessado.Municipio = municipio;// aplMunicipio.ConsultarPorNome(ds.Tables[0].Rows[i].ItemArray[13].ToString().ToUpper());

    if (!String.IsNullOrEmpty(ds.Tables[0].Rows[linha].ItemArray[11].ToString()))
    {
    //Bairro bairro = aplBairro.ConsultarPorNomeCodMunicipio(ds.Tables[0].Rows[linha].ItemArray[11].ToString().ToUpper(), municipio.Codigo);
    List listaBairro = aplBairro.ListaPorIdMunicipio(municipio.Codigo);
    Bairro bairro = listaBairro.Find(b => Utilitarios.RemoveAcentos(b.Descricao).ToUpper() == Utilitarios.RemoveAcentos(ds.Tables[0].Rows[linha].ItemArray[11].ToString()).ToUpper());
    if (bairro == null)
    {
    bairro = new Bairro();
    bairro.CodMunicipio = municipio;
    bairro.Descricao = ds.Tables[0].Rows[linha].ItemArray[11].ToString().ToUpper();
    aplBairro.gravar(bairro);
    }
    interessado.Bairro = bairro;// aplBairro.ConsultarPorNomeCodMunicipio(ds.Tables[0].Rows[i].ItemArray[11].ToString().ToUpper(), municipio.Codigo);
    }
    }
    if (!ds.Tables[0].Rows[linha].ItemArray[12].ToString().Equals(“”))
    interessado.Cep = ds.Tables[0].Rows[linha].ItemArray[12].ToString();
    if (!ds.Tables[0].Rows[linha].ItemArray[7].ToString().Equals(“”))
    if (ds.Tables[0].Rows[linha].ItemArray[7].ToString().Length == 14)
    {
    interessado.CPF_CNPJ = AuxiliarCPF_CNPJ.DesformataCPF(ds.Tables[0].Rows[linha].ItemArray[7].ToString());
    interessado.Tipo = 1;
    }
    else if (ds.Tables[0].Rows[linha].ItemArray[7].ToString().Length == 18)
    {
    interessado.CPF_CNPJ = AuxiliarCPF_CNPJ.DesformataCNPJ(ds.Tables[0].Rows[linha].ItemArray[7].ToString());
    interessado.Tipo = 2;
    }
    else
    {
    log.Append(“O CPF/CNPJ informado na célula H” + (linha + 1) + ” está em um formato incorreto. Favor corrigir a planilha. “);
    arquivoInvalidado = true;
    }
    return interessado;
    }

    private void setProcInter(Processo processo, Interessado interessado, DataSet ds, int i)
    {
    ProcessoInteressado processoInteressado = new ProcessoInteressado();
    NumberFormatInfo numberFormatInfo = new NumberFormatInfo();
    numberFormatInfo.NumberDecimalSeparator = “,”;
    try
    {
    if (processo == null)
    processo = new Processo();
    if (!ds.Tables[0].Rows[i].ItemArray[14].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Equals(“”))
    {
    processoInteressado.ValorBruto = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[14].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    //processoInteressado.ValorBruto_Up = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[14].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    processoInteressado.ValorBrutoPago = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[14].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    }
    if (!ds.Tables[0].Rows[i].ItemArray[15].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Equals(“”))
    {
    processoInteressado.ValorIR = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[15].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    //processoInteressado.ValorIR_Up = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[15].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    processoInteressado.ValorIRPago = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[15].ToString().Replace(“R$”, “”).Replace(” “, “”).Replace(“-“, “”).Replace(“.”, “”), numberFormatInfo);
    }
    if (!ds.Tables[0].Rows[i].ItemArray[17].ToString().Equals(“”))
    processoInteressado.CodigoSep = decimal.Parse(ds.Tables[0].Rows[i].ItemArray[17].ToString());
    else
    processoInteressado.CodigoSep = null;
    try
    {
    DateTime DataSep = DateTime.Parse(ds.Tables[0].Rows[i].ItemArray[18].ToString());
    processoInteressado.DataSep = DataSep;
    }
    catch
    {
    logErro.Append(“A célula S” + (i + 1) + ” deve estar preenchida com uma data. “);
    arquivoInvalidado = true;
    }
    try
    {
    DateTime DataEntradaSefaz = DateTime.Parse(ds.Tables[0].Rows[i].ItemArray[19].ToString());
    processoInteressado.DataEntradaSefaz = DataEntradaSefaz;
    }
    catch
    {
    logErro.Append(“A célula T” + (i + 1) + ” deve estar preenchida com uma data. “);
    arquivoInvalidado = true;
    }
    try
    {
    DateTime DataRequisicaoPgto = DateTime.Parse(ds.Tables[0].Rows[i].ItemArray[0].ToString());
    processoInteressado.DataDoValorBruto = DataRequisicaoPgto;
    }
    catch
    {
    logErro.Append(“A célula A” + (i + 1) + ” deve estar preenchida com uma data. “);
    arquivoInvalidado = true;
    }
    processoInteressado.Interessado = interessado;
    processoInteressado.Processo = aplProcesso.consultarPorNProcessoER(processo.NumProcessoJudicial);

    listaGravarProcInter.Add(processoInteressado);
    listaLogsAuditoria.Add(“Importação de Processo Interessado. Número Judicial do Processo: ” + processoInteressado.Processo.NumProcessoJudicial + “; Interessado: ”
    + processoInteressado.Interessado.Nome + ” – ” + processoInteressado.Interessado.CPF_CNPJ + “; Valor bruto: ” + processoInteressado.ValorBruto + “; IRPF: ” + processoInteressado.ValorIR + “.”);
    }
    catch (Exception erro)
    {
    arquivoInvalidado = true;
    logErro.Append(erro.Message + “”);
    }
    }

    private bool VerificaLayout(DataSet ds)
    {
    if (!ds.Tables[0].Rows[4].ItemArray[0].Equals(“Data de Requisição do Pgto”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[1].Equals(“NUMERO PROCESSO ANTERIOR”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[2].Equals(“NUMERO JUDICIAL”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[3].Equals(“COMARCA”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[4].Equals(“VARA”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[5].Equals(“VARANOME”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[6].Equals(“NOME”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[7].Equals(“CPF”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[8].Equals(“DEENDERECO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[9].Equals(“NUENDERECO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[10].Equals(“DECOMPLEMENTO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[11].Equals(“DEBAIRRO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[12].Equals(“NUCEP”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[13].Equals(“NMMUNICIPIO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[14].Equals(“BRUTO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[15].Equals(“IRPF”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[16].Equals(“LIQUIDO”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[17].Equals(“Nº SEP”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[18].Equals(“DATA SEP”))
    return false;
    if (!ds.Tables[0].Rows[4].ItemArray[19].Equals(“DATA DE RECEBIMENTO NA ORIGEM”))
    return false;

    return true;
    }

    private void VerificacaoPreliminar(int count, DataSet ds)
    {
    bool importado = false;
    for (int i = 5; i < count; i++)
    {
    //Verifica se nenhuma planilha com o numSEP informado já não foi importada
    if (!ds.Tables[0].Rows[i].ItemArray[17].ToString().Equals(""))
    {
    if (aplProcessoInteressado.listaProcInterPorCodSep(decimal.Parse(ds.Tables[0].Rows[i].ItemArray[17].ToString())).Count != 0)
    {
    importado = true;
    break;
    }
    }
    else
    {
    log.Append("A célula S" + (i + 1) + " deve ser preenchida. “);
    arquivoInvalidado = true;
    }
    if (!importado)
    {
    //Validação de campos obrigatórios
    if (ds.Tables[0].Rows[i].ItemArray[6].ToString().Equals(“”))
    {
    log.Append(“A célula G” + (i + 1) + ” deve ser preenchida. “);
    arquivoInvalidado = true;
    }
    if (ds.Tables[0].Rows[i].ItemArray[7].ToString().Equals(“”))
    {
    log.Append(“A célula H” + (i + 1) + ” deve ser preenchida. “);
    arquivoInvalidado = true;
    }
    if (ds.Tables[0].Rows[i].ItemArray[14].ToString().Equals(“”))
    {
    log.Append(“A célula O” + (i + 1) + ” deve ser preenchida. “);
    arquivoInvalidado = true;
    }

    //Valida se pelo menos uma das colunas de NumProcesso está preenchida
    if (ds.Tables[0].Rows[i].ItemArray[1].ToString() == “” && ds.Tables[0].Rows[i].ItemArray[2].ToString() == “”)
    {
    log.Append(“A célula B” + (i + 1) + ” e/ou a célula C” + (i + 1) + ” devem estar preenchidas. “);
    arquivoInvalidado = true;
    }

    //Valida se a vara e comarca estão preenchidas no arquivo
    if (ds.Tables[0].Rows[i].ItemArray[3].ToString().Equals(“”))
    {
    log.Append(“A célula D” + (i + 1) + ” deve ser preenchida. “);
    arquivoInvalidado = true;
    }
    if (ds.Tables[0].Rows[i].ItemArray[5].ToString().Equals(“”))
    {
    log.Append(“A célula F” + (i + 1) + ” deve ser preenchida. “);
    arquivoInvalidado = true;
    }
    //Valida a consistencia da vara, comarca e numvara.
    if (!ds.Tables[0].Rows[i].ItemArray[3].ToString().Equals(“”) &&
    !ds.Tables[0].Rows[i].ItemArray[5].ToString().Equals(“”))
    {
    List listaVaraComarca = aplVaraExecucao.ConsultarPorNomeVaraNomeComarca(ds.Tables[0].Rows[i].ItemArray[5].ToString().Trim(), ds.Tables[0].Rows[i].ItemArray[3].ToString().Trim());
    if (listaVaraComarca.Count == 0)
    {
    log.Append(“No sistema não existe vara de execução associada a comarca informada na linha ” + (i + 1) + “. Favor corrigir o sistema. “);
    arquivoInvalidado = true;
    }
    else
    {
    VaraExecucao vara = new VaraExecucao();
    if (ds.Tables[0].Rows[i].ItemArray[4].ToString().Equals(“”))
    {
    vara = listaVaraComarca.Find(o => o.NumeroVara == null);
    }
    else
    {
    vara = listaVaraComarca.Find(o => o.NumeroVara == int.Parse(ds.Tables[0].Rows[i].ItemArray[4].ToString().Trim()));
    }
    if (vara == null || vara.Codigo == 0)
    {
    log.Append(“O número da vara informado na célula E” + (i + 1) + ” não corresponde a vara e comarca informada. Favor corrigir o sistema ou a planilha. “);
    arquivoInvalidado = true;
    }
    }
    }
    if (listaInteressadoArq.Count != 0)
    {
    if (!listaInteressadoArq.Exists(o => o.Nome.Equals(ds.Tables[0].Rows[i].ItemArray[6].ToString().ToUpper())))
    listaInteressadoArq.Add(this.setInteressado(ds, i));
    else //apenas para verificar os dados do interessado informados na planilha
    setInteressado(ds, i);
    }
    else
    listaInteressadoArq.Add(this.setInteressado(ds, i));
    }
    }//fim For
    if(importado)
    {
    log.Append(“Uma planilha com o Nº SEP informado já foi importada. “);
    arquivoInvalidado = true;
    }
    }

    private Interessado PesquisaInteressado(string nome, string cpf)
    {
    Interessado interessado = new Interessado();
    interessado = aplInteressado.ConsultarPorCPF(cpf);
    if (interessado != null)
    {
    return interessado;
    }
    else
    {
    try
    {
    interessado = aplInteressado.ConsultarPorNome(nome);
    if (interessado != null)
    {
    //atualiza interessado
    return interessado;
    }
    }
    catch
    {
    arquivoInvalidado = true;
    logErro.Append(“O registro do interessado ” + nome + ” está duplicado no sistema. Favor corrigir. “);
    }
    }
    return null;
    }

    private DataTable DadosExcel(string caminho)
    {
    Char aspas = ‘”‘;

    //OleDbConnection conexao = new OleDbConnection(@”Provider=Microsoft.ACE.OLEDB.12.0;Data Source=”” + caminho + “”;Extended Properties=’Excel 12.0;HDR=No;IMEX=1’;”);
    string Conexao = “Provider=Microsoft.ACE.OLEDB.12.0;” +
    “Data Source=” + caminho + “;” +
    “Extended Properties=” + aspas + “Excel 12.0;HDR=No;IMEX=1” + aspas;
    System.Data.OleDb.OleDbConnection Cn = new System.Data.OleDb.OleDbConnection();
    Cn.ConnectionString = Conexao;
    Cn.Open();
    object[] Restricoes = { null, null, null, “TABLE” };
    DataTable DTSchema = Cn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, Restricoes);
    if (DTSchema.Rows.Count > 0)
    {
    string Sheet = DTSchema.Rows[0][“TABLE_NAME”].ToString();
    System.Data.OleDb.OleDbCommand Comando = new System.Data.OleDb.OleDbCommand(“SELECT * FROM [” + Sheet + “]”, Cn);
    DataTable Dados = new DataTable();
    System.Data.OleDb.OleDbDataAdapter DA = new System.Data.OleDb.OleDbDataAdapter(Comando);
    DA.Fill(Dados);
    Cn.Close();
    return Dados;
    }
    return null;
    }

    public void ValidaDuplicidadeInteressado()
    {
    if (listaInteressadoArq.Count != 0)
    {
    List listaInterAux = new List();
    List listaProc = new List();
    List listaProcInter = new List();
    List listaTodosInteressados = aplInteressado.listaTodos();
    String logAlteracaoInter = String.Empty;

    foreach (var inter in listaInteressadoArq)
    {
    if (listaTodosInteressados.Exists(i => i.CPF_CNPJ == inter.CPF_CNPJ || i.Nome.Contains(inter.Nome)))
    {
    listaInterAux = listaTodosInteressados.FindAll(i => i.CPF_CNPJ == inter.CPF_CNPJ || i.Nome.Contains(inter.Nome));

    if (listaInterAux.Count > 1)
    {
    //Atualização de interessado duplicado e alterações necessárias para o caso
    logAlteracaoInter = “Importação – Alteração do Interessado, Nome: ” + listaInterAux.First().Nome + “, CPF/CNPJ: ” + listaInterAux.First().CPF_CNPJ
    + “, Endereço: ” + listaInterAux.First().Endereco + “, nº: ” + listaInterAux.First().Numero + “, Cep: ” + listaInterAux.First().Cep
    + “, Bairro: ” + (listaInterAux.First().Bairro != null ? listaInterAux.First().Bairro.Descricao : String.Empty) + “, Municipio: ” + (listaInterAux.First().Municipio != null ? listaInterAux.First().Municipio.Nome : String.Empty) + “, Complemento: ” + listaInterAux.First().Complemento
    + “.’\n'” + “Para ‘\n'”;

    Interessado interessado = new Interessado();
    interessado = listaInterAux.First();

    interessado.Bairro = inter.Bairro;
    interessado.Cep = inter.Cep;
    interessado.Complemento = inter.Complemento;
    interessado.CPF_CNPJ = inter.CPF_CNPJ;
    interessado.Endereco = inter.Endereco;
    interessado.Municipio = inter.Municipio;
    interessado.Nome = inter.Nome;
    interessado.Numero = inter.Numero;

    listaInterAux.Remove(listaInterAux.First());

    aplInteressado.gravar(interessado);

    logAlteracaoInter += “Nome: ” + interessado.Nome + “, CPF/CNPJ: ” + interessado.CPF_CNPJ + “, Endereço: ” + interessado.Endereco
    + “, nº: ” + interessado.Numero + “, Cep: ” + interessado.Cep + “, Bairro: ” + (interessado.Bairro != null ? interessado.Bairro.Descricao : String.Empty )
    + “, Municipio: ” + (interessado.Municipio != null ? interessado.Municipio.Nome : String.Empty) + “, Complemento: ” + interessado.Complemento + “.”;

    listaLogsAuditoria.Add(logAlteracaoInter);

    listaProc = aplProcesso.consultaPorInteressado(interessado); //aplProcesso.consultarPorCpfInteressado(inter.CPF);
    foreach (var item in listaProc)
    {
    item.Interessado = interessado;
    aplProcesso.gravar(item);
    listaLogsAuditoria.Add(“Importação – Alteração do processo de número judicial ” + item.NumProcessoJudicial +
    “. Alterado Interessado por motivo de duplicidade de CPF/CNPJ.”);
    }

    listaProcInter = aplProcessoInteressado.listaProcInterPorInteressado(interessado);// aplProcessoInteressado.listaProcInterPorCpf(inter.CPF);
    foreach (var item in listaProcInter)
    {
    item.Interessado = interessado;
    aplProcessoInteressado.salvar(item);
    listaLogsAuditoria.Add(“Importação – Alteração do processo/interessado código: ” + item.Codigo +
    “, pertencente ao Processo: ” + item.Processo.NumProcessoJudicial +
    “. Alterado Interessado por motivo de duplicidade de CPF/CNPJ.”);
    }

    while (listaInterAux.Count != 0)
    {
    try
    {
    listaLogsAuditoria.Add(“Importação – Exclusão do Interessado: ” + listaInterAux.First().Nome + ” – ” + listaInterAux.First().CPF_CNPJ + “. Por motivo de duplicidade de CPF/CNPJ.”);
    Interessado interessadoDel = listaInterAux.First();
    listaInterAux.Remove(interessadoDel);
    aplInteressado.deletar(interessadoDel);
    }
    catch (Exception erro)
    {
    ExibirMessageBoxException(erro.Message);
    }
    }
    }
    else
    {
    //Atualização de interessado existente
    Interessado interessado = new Interessado();
    interessado = listaInterAux.First();

    if (!this.InteressadoIgual(interessado, inter))
    {
    logAlteracaoInter = “Importação – Alteração do Interessado, Nome: ” + listaInterAux.First().Nome + “, CPF/CNPJ: ” + listaInterAux.First().CPF_CNPJ
    + “, Endereço: ” + listaInterAux.First().Endereco + “, nº: ” + listaInterAux.First().Numero + “, Cep: ” + listaInterAux.First().Cep
    + “, Bairro: ” + (listaInterAux.First().Bairro != null ? listaInterAux.First().Bairro.Descricao : String.Empty) + “, Municipio: ”
    + (listaInterAux.First().Municipio != null ? listaInterAux.First().Municipio.Nome : String.Empty) + “, Complemento: ” + listaInterAux.First().Complemento
    + “.’\n'” + “Para ‘\n'”;

    aplInteressado.gravar(interessado);

    logAlteracaoInter += “Nome: ” + interessado.Nome + “, CPF/CNPJ: ” + interessado.CPF_CNPJ + “, Endereço: ” + interessado.Endereco
    + “, nº: ” + interessado.Numero + “, Cep: ” + interessado.Cep + “, Bairro: ” + (interessado.Bairro != null ? interessado.Bairro.Descricao : String.Empty)
    + “, Municipio: ” + (interessado.Municipio != null ? interessado.Municipio.Nome : String.Empty) + “, Complemento: ” + interessado.Complemento + “.”;
    listaLogsAuditoria.Add(logAlteracaoInter);
    }
    }
    }
    else
    {
    //Novo interessado
    aplInteressado.gravar(inter);
    logAlteracaoInter = “Importação – Cadastro do Interessado, Nome: ” + inter.Nome + “, CPF/CNPJ: ” + inter.CPF_CNPJ + “, Endereço: ” + inter.Endereco + “, nº: ” + inter.Numero
    + “, Cep: ” + inter.Cep + “, Bairro: ” + (inter.Bairro != null ? inter.Bairro.Descricao : String.Empty) + “, Municipio: ” + (inter.Municipio != null ? inter.Municipio.Nome : String.Empty) + “, Complemento: ” + inter.Complemento + “.”;
    listaLogsAuditoria.Add(logAlteracaoInter);
    }
    }//fim Foreach
    }
    }

    //Verifica interessados antes de atualizar
    public Boolean InteressadoIgual(Interessado oldInter, Interessado newInter)
    {
    //Retorna true se os interessados forem iguais
    Boolean retorno = true;

    if (!oldInter.Nome.Equals(newInter.Nome))
    {
    retorno = false;
    oldInter.Nome = newInter.Nome;
    }
    if (oldInter.CPF_CNPJ == null || !oldInter.CPF_CNPJ.Equals(newInter.CPF_CNPJ))
    {
    retorno = false;
    oldInter.CPF_CNPJ = newInter.CPF_CNPJ;
    }
    if ((oldInter.Endereco == null && newInter.Endereco != null) || oldInter.Endereco != newInter.Endereco)
    {
    retorno = false;
    oldInter.Endereco = newInter.Endereco;
    }
    if ((oldInter.Numero == null && newInter.Numero != null) || oldInter.Numero != newInter.Numero)
    {
    retorno = false;
    oldInter.Numero = newInter.Numero;
    }
    if ((oldInter.Cep == null && newInter.Cep != null) || oldInter.Cep != newInter.Cep)
    {
    retorno = false;
    oldInter.Cep = newInter.Cep;
    }
    if (oldInter.Bairro != null)
    {
    if (newInter.Bairro != null)
    {
    if (oldInter.Bairro.Codigo != newInter.Bairro.Codigo)
    {
    retorno = false;
    oldInter.Bairro = newInter.Bairro;
    }
    }
    }
    else
    {
    if (newInter.Bairro != null)
    {
    retorno = false;
    oldInter.Bairro = newInter.Bairro;
    }
    }
    if (oldInter.Municipio != null)
    {
    if (newInter.Municipio != null)
    {
    if (oldInter.Municipio.Codigo != newInter.Municipio.Codigo)
    {
    retorno = false;
    oldInter.Municipio = newInter.Municipio;
    }
    }
    }
    else
    {
    if (newInter.Municipio != null)
    {
    retorno = false;
    oldInter.Municipio = newInter.Municipio;
    }
    }

    if ((oldInter.Complemento == null && newInter.Complemento != null) || oldInter.Complemento != newInter.Complemento)
    {
    retorno = false;
    oldInter.Complemento = newInter.Complemento;
    }
    return retorno;
    }

    }
    }

    • andrealveslima disse:

      Olá Robson!

      Obrigado pelo comentário.. É impossível simplesmente analisar a performance de um código de mais de 700 linhas simplesmente colando aqui no comentário.. Não rola.. Problemas de performance podem acontecer por uma infinidade de motivos..

      Pode ser que o Dapper te ajude a melhorar a performance? Se o problema estiver na questão de você estar mapeando dados do banco em instâncias de classe, sim o Dapper pode ajudar.. Agora, se o problema de performance não for esse, aí não vai adiantar de nada..

      A minha sugestão é que você rode um profiler nessa sua aplicação para primeiro entender onde é que realmente está o problema de performance dela.. Se for realmente no mapeamento do banco para instâncias de classe, aí você pode utilizar os conceitos que eu demonstrei aqui no artigo para ajustar a sua aplicação..

      Abraço!
      André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *