André Alves de Lima

Talking about Software Development and more…

Trabalhando com o LocalDb no C# e VB.NET

Nem toda aplicação precisa de um banco de dados robusto como SQL Server, Oracle, PostgreSQL, MySQL, entre outros. Muitas vezes a base de dados da nossa aplicação não será tão grande e não precisará de muitos recursos, o que acaba não justificando a utilização de um SGBD completo para lidar com os dados do aplicativo. É para esse tipo de cenário que existem os bancos de dados locais, entre eles, o LocalDb. No artigo de hoje, eu vou mostrar tudo o que você precisa saber para trabalhar com o LocalDb no C# e VB.NET.

O LocalDb não é o único banco de dados local que você pode utilizar na sua aplicação. Por exemplo, uns tempos atrás eu escrevi um artigo mostrando como trabalhar com o SQLite no C# e VB.NET, que é um dos bancos de dados locais mais utilizados no mercado. Como você pode conferir nesse artigo, no caso do SQLite, nós não precisamos instalar absolutamente nada. Basta adicionarmos uma referência pelo NuGet, baixar uma ferramenta para criar o arquivo do banco de dados e pronto, já podemos sair utilizando o SQLite nas nossas aplicações.

Com o LocalDb, apesar do processo ser simples, as coisas são um pouquinho mais complicadas do que com o SQLite. Ele é um banco de dados local, mas que precisa de instalação. Por trás dos panos, ele é basicamente uma instalação do SQL Server Express, mas com a limitação de não permitir conexões remotas. Como ele depende desse processo de instalação, o primeiro passo que eu vou demonstrar neste artigo é a utilização dele no computador de desenvolvimento.

Instalando o LocalDb no computador de desenvolvimento

Quando fazemos uma instalação padrão do Visual Studio 2017 utilizando as workloads para desenvolvimento desktop ou web, o LocalDb será instalado no mesmo bolo. Se você der uma olhada na parte de “Individual components“, você perceberá que o item “SQL Server Express 2016 LocalDb” foi marcado automaticamente:

Nota: se eu não me engano, a instalação padrão do Visual Studio 2015 também instala uma instância do LocalDb automaticamente.

Caso você não tenha certeza, abra o setup do Visual Studio e veja se essa opção está marcada no seu ambiente. Se ela estiver marcada, isso significa que o LocalDb já está instalado no seu computador de desenvolvimento e está pronto para ser utilizado. Caso contrário, marque essa opção para que você possa utilizar o LocalDb durante o desenvolvimento da sua aplicação.

Listando as instâncias do LocalDb

A instalação padrão do LocalDb criará uma instância chamada “MSSQLLocalDB“. Você pode listar as instâncias do LocalDb em um prompt utilizando o comando “sqllocaldb info“:

Nós podemos criar novas instâncias através do comando “sqllocaldb create NOME_DA_INSTANCIA“, porém, no artigo de hoje nós vamos utilizar a instância padrão que foi criada automaticamente pela instalação do LocalDb (MSSQLLocalDB). Aliás, o comando “sqllocaldb” traz uma infinidade de possibilidades. Para listar todas as opções, utilize o comando “sqllocaldb /?“:

Conectando no LocalDb com o Management Studio

Do ponto de vista do computador onde o LocalDb está sendo executado, ele parece ser um banco de dados SQL Server Express. Ou seja, você consegue se conectar ao LocalDb utilizando o SQL Server Management Studio da mesma forma que você faria para se conectar a um SQL Server Express. A única diferença está no endereço do servidor.

Para conseguirmos nos conectar a um LocalDb a partir do Management Studio, nós temos que informar o endereço “(localdb)\NOME_DA_INSTANCIA“. Como mencionado anteriormente, no caso da instalação padrão, o nome da instância é “mssqllocaldb“, portanto, a conexão pode ser feita dessa maneira:

Uma vez conectado, você consegue gerenciar o LocalDb como se ele fosse uma instância do SQL Server Express:

Você pode criar novos bancos, atachar arquivos MDF existentes, criar tabelas, fazer backup e restore, etc. Ou seja, você consegue fazer tudo o que você conseguiria com uma instância do SQL Server Express.

Connection string para utilização do LocalDb

Seguindo a mesma lógica do endereço que utilizamos no Management Studio, para nos conectarmos a um LocalDb através da nossa aplicação, nós conseguimos utilizar a mesma string de conexão do SQL Server Express, alterando somente a parte do endereço. Veja como ficaria um exemplo de string de conexão para o LocalDb:

Server=(localdb)\mssqllocaldb; Integrated Security=true; Initial Catalog=DemoLocalDb;

Nota: um dos sites mais famosos com exemplos de strings de conexão é o www.connectionstrings.com, porém as strings de conexão para o LocalDb que estavam listadas nesse site não funcionaram em nenhum dos cenários que eu testei.

Pequeno exemplo de acesso com o ADO.NET

Eu já mencionei isso algumas vezes nesse artigo, mas eu vou repetir novamente: por trás dos panos, o LocalDb é como um SQL Server Express. Dito isso, não é surpresa que nós conseguimos acessar e manipular os dados de uma instância do LocalDb via código exatamente da mesma maneira que fazemos com um SQL Server “normal“. Ou seja, com o ADO.NET e as classes do namespace “System.Data.SqlClient“, nós conseguimos fazer consultas na nossa instância do LocalDb.

Para demonstrarmos o funcionamento, vamos criar um novo projeto do tipo “Console Application“. Dentro desse projeto, vamos adicionar um arquivo MDF existente, chamado de “BancoDeDados.mdf“. Nesse arquivo MDF, nós teremos somente uma tabela chamada “Pessoa“, com os campos “Id“, “Nome” e “Sobrenome“:

Eu adicionei dois registros de exemplo dentro dessa tabela (para podermos lista-los através da nossa aplicação). Caso seja necessário, você pode criar esse MDF manualmente através da opção “Adicionar novo item ao projeto -> Service-based Database“:

Nota: para facilitar um pouco as coisas, caso você não queira criar esse arquivo manualmente, você pode baixa-lo através deste link. Descompacte o arquivo zip e adicione o MDF no projeto através do Solution Explorer (botão direito no projeto -> adicionar item existente).

Uma vez adicionado o MDF ao projeto, certifique-se que ele esteja marcado com a opção “Copy if newer” na configuração “Copy to Output Directory” dentro da janela de propriedades. Dessa forma, o arquivo somente será sobrescrito na pasta “bin/debug” caso alguma alteração seja feita no arquivo MDF original. A configuração padrão é “Copy always“, e isso faz com que o banco sempre seja sobrescrito, o que normalmente não é o comportamento esperado.

Feito isso, nós podemos criar uma nova conexão normalmente com o LocalDb e atachar esse arquivo MDB na nossa instância padrão (“mssqllocaldb“). Veja como ficaria o código para atachar o banco e listar o conteúdo da tabela “Pessoa“:

            // C#
            Console.WriteLine("ADO.NET:");
            var caminhoBanco = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "BancoDeDados.mdf");
            var stringConexao = string.Format(@"Server=(localdb)\mssqllocaldb; Integrated Security=true; AttachDbFileName={0};", caminhoBanco);

            using (var conn = new System.Data.SqlClient.SqlConnection(stringConexao))
            {
                conn.Open();
                if (conn.State == System.Data.ConnectionState.Open)
                {
                    using (var comm = new System.Data.SqlClient.SqlCommand())
                    {
                        comm.Connection = conn;
                        comm.CommandText = "SELECT * FROM Pessoa";
                        using (var reader = comm.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                Console.WriteLine("ID: {0}, Nome: {1}, Sobrenome: {2}", reader["Id"], reader["Nome"], reader["Sobrenome"]);
                            }
                        }
                    }
                }
            }
            Console.ReadLine();
        ' VB.NET
        Console.WriteLine("ADO.NET:")
        Dim CaminhoBanco = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "BancoDeDados.mdf")
        Dim StringConexao = String.Format("Server=(localdb)\mssqllocaldb; Integrated Security=true; AttachDbFileName={0};", CaminhoBanco)
        Using Conn = New System.Data.SqlClient.SqlConnection(StringConexao)
            Conn.Open()
            If Conn.State = System.Data.ConnectionState.Open Then
                Using Comm = New System.Data.SqlClient.SqlCommand()
                    Comm.Connection = Conn
                    Comm.CommandText = "SELECT * FROM Pessoa"
                    Using Reader = Comm.ExecuteReader()
                        While Reader.Read()
                            Console.WriteLine("ID: {0}, Nome: {1}, Sobrenome: {2}", Reader("Id"), Reader("Nome"), Reader("Sobrenome"))
                        End While
                    End Using
                End Using
            End If
        End Using

        Console.ReadLine()

Observe que não temos absolutamente nada de especial no código apresentado acima. A única diferença entre uma conexão com um banco SQL Server “de verdade” e o LocalDb é o endereço do banco de dados na string de conexão. Execute o código e veja o resultado:

Funciona com o Entity Framework?

Se o LocalDb é, na verdade, um SQL Server Express com menos capacidades, será que ele funcionaria também com o Entity Framework? E a resposta é sim! Ele funciona com o Entity Framework também!

Vamos demonstrar isso criando um pequeno exemplo utilizando a estratégia “code first“. Primeiramente, vamos criar a classe correspondente à nossa tabela:

    // 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 a referência ao Entity Framework pelo NuGet:

Feito isso, vamos adicionar a nossa classe de contexto, que terá o DbSet para a classe “Pessoa“:

    // C#
    public class Contexto : DbContext
    {
        public Contexto(string connectionString) : base(connectionString) {  }

        public DbSet<Pessoa> Pessoas { get; set; }
    }
' VB.NET
Public Class Contexto
    Inherits DbContext

    Public Sub New(ByVal connectionString As String)
    End Sub

    Public Property Pessoas As DbSet(Of Pessoa)
End Class

Agora que nós já temos tudo preparado, nós podemos simplesmente criar uma instância do nosso contexto e trabalhar com o conteúdo da coleção de pessoas (que estará mapeada para a tabela de pessoas no banco de dados). Primeiramente, vamos percorrer a coleção de pessoas, excluindo todo o seu conteúdo. Em seguida, nós adicionamos duas pessoas nessa coleção e percorremos novamente a coleção para imprimirmos no console:

            // C#
            Console.WriteLine("Entity Framework");
            var stringConexaoEF = @"Server=(localdb)\mssqllocaldb; Integrated Security=true; Initial Catalog=DemoLocalDb;";
            using (var contexto = new Contexto(stringConexaoEF))
            {
                foreach (var pessoa in contexto.Pessoas)
                {
                    contexto.Pessoas.Remove(pessoa);
                }
                contexto.SaveChanges();

                contexto.Pessoas.Add(new Pessoa() { Nome = "Andre", Sobrenome = "Alves de Lima" });
                contexto.Pessoas.Add(new Pessoa() { Nome = "Fulano", Sobrenome = "de Tal" });
                contexto.SaveChanges();
            }
            using (var contexto = new Contexto(stringConexaoEF))
            {
                foreach (var pessoa in contexto.Pessoas)
                {
                    Console.WriteLine("ID: {0}, Nome: {1}, Sobrenome: {2}", pessoa.Id, pessoa.Nome, pessoa.Sobrenome);
                }
            }
            Console.ReadLine();
        ' VB.NET
        Console.WriteLine("Entity Framework")
        Dim StringConexaoEF = "Server=(localdb)\mssqllocaldb; Integrated Security=true; Initial Catalog=DemoLocalDb;"
        Using Contexto = New Contexto(StringConexaoEF)
            For Each Pessoa In Contexto.Pessoas
                Contexto.Pessoas.Remove(Pessoa)
            Next

            Contexto.SaveChanges()
            Contexto.Pessoas.Add(New Pessoa() With {.Nome = "Andre", .Sobrenome = "Alves de Lima"})
            Contexto.Pessoas.Add(New Pessoa() With {.Nome = "Fulano", .Sobrenome = "de Tal"})
            Contexto.SaveChanges()
        End Using

        Using Contexto = New Contexto(StringConexaoEF)
            For Each Pessoa In Contexto.Pessoas
                Console.WriteLine("ID: {0}, Nome: {1}, Sobrenome: {2}", Pessoa.Id, Pessoa.Nome, Pessoa.Sobrenome)
            Next
        End Using

        Console.ReadLine()

E qual será o resultado? Veja na imagem abaixo:

Por trás dos panos, o Entity Framework criou a tabela automaticamente dentro do banco chamado “DemoLocalDb” (nome que foi informado como “Initial Catalog” na string de conexão):

Nota: se você não tem familiaridade com esses conceitos do Entity Framework, sugiro que você dê uma olhada no meu artigo introdutório sobre Entity Framework.

Instalando o LocalDb no computador do cliente

Até aqui nós só falamos sobre o ambiente de desenvolvimento, mas como é que fica no computador do cliente? Como nós instalamos o LocalDb nas máquinas onde a nossa aplicação será executada?

Para instalar o LocalDb no computador cliente, primeiramente nós precisamos fazer o download dele. Esse é um ponto que pode ser um pouco confuso. Para baixarmos o instalador do LocalDb, nós precisamos, na verdade, baixar o instalador do SQL Server 2016 Express. O Scott Hanselman facilita muito a nossa vida listando aqui os links para download de todas as versões do SQL Server Express.

Uma vez baixado e executado o instalador da versão 2016 Express, nós temos que escolher a opção “Download Media“:

Em seguida, nós conseguiremos baixar o instalador do LocalDb através desta opção:

Nota: caso você queira pular esses passos, eu baixei o instalador do SQL Server 2016 Express LocalDb e estou disponibilizando para download direto através deste link.

Pronto! É esse arquivo “SqlLocalDB.msi” que nós temos que instalar no computador do cliente. Nós podemos fazer a instalação manual do LocalDb (executando esse arquivo msi) ou, caso você tenha criado um instalador para a sua aplicação, você pode executar esse msi de maneira silenciosa através do seguinte comando:

msiexec /i SqlLocalDB.msi /qn IACCEPTSQLLOCALDBLICENSETERMS=YES

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

Apesar do LocalDb ser um banco de dados local um tanto quanto enxuto (seu instalador tem quase 50Mb ao todo), o seu deployment é mais complicado do que o SQLite, onde nós só precisamos distribuir o arquivo do banco de dados e algumas dlls extras com a nossa aplicação.

No artigo de hoje você viu como habilitar o LocalDb no computador de desenvolvimento e como acessá-lo através do ADO.NET e Entity Framework. Por fim, eu mostrei para você o processo de instalação do LocalDb nos computadores clientes.

O LocalDb é uma excelente opção de banco de dados local. Ele é realmente um banco de dados completo, suportando todas as funcionalidades do SQL Server Express, porém, rodando no modo “usuário local” e, como o próprio nome já diz, não permitindo conexões remotas.

Se você estiver desenvolvendo uma aplicação “do zero” e estiver à procura de um banco de dados local, eu particularmente recomendo a utilização do SQLite como uma primeira opção. Eu somente partiria para a utilização do LocalDb em duas situações:

1) Caso as capacidades do SQLite não estejam dando conta do recado (porém, nesse caso eu acredito que eu partiria direto para o SQL Server Express)

2) Caso você já tenha a aplicação desenvolvida utilizando as classes do SQL Server (SqlConnection, SqlCommand, etc)

Mas, de qualquer forma, sempre é bom conhecermos as opções que nós temos à nossa disposição.

E você, utiliza o LocalDb como banco de dados local para a sua aplicação? Quais foram as suas experiências? Recomenda a sua utilização? Deixe as suas impressões na caixa de comentários logo abaixo.

Até a próxima!

André Lima

Newsletter do André Lima

* indicates required



Powered by MailChimp

12 thoughts on “Trabalhando com o LocalDb no C# e VB.NET

  • VAlter disse:

    A furada é ter que instalar. O SQLite não precisa…

    • andrealveslima disse:

      Olá Valter!

      Sim, o SQLite é bem mais simples mesmo, não precisa de instalação.. Por outro lado, o LocalDb tem todo o poder do SQL Server Express com uma instalação bem pequena.. Tem que pesar os prós e contras para ver o que faz sentido em cada projeto..

      Abraço!
      André Lima

  • Claudio disse:

    Poderia ser utilizado em cliente em casos onde seria utilizado apenas uma máquina, sem a necessidade de máquina servidora e máquinas clientes?

    Aproveitando… da para utilizar em rede?

    • andrealveslima disse:

      Olá Claudio!

      Respondendo às suas perguntas:

      1) Sim, o LocalDb pode ser utilizado sem a necessidade de máquina servidora.. Aliás, esse é justamente o cenário onde ele se encaixa.. O LocalDb deve ser instalado nos computadores clientes (cenários em que cada computador tem o seu banco de dados individual)..

      2) Não, o LocalDb só pode ser acessado localmente, e não pela rede (daí o nome “Local”Db)..

      Abraço!
      André Lima

  • Evandro disse:

    Parabéns, muito bom!!

  • Anderson disse:

    Excelente publicação,
    estou desenvolvendo um projeto para gerenciar motoclube, até o momento estava utilizando os recurso do ADO.Net com access, porém estava gastando muito tempo escrevendo tudo à mão.
    Comecei utilizar o entity-framework porém a dúvida ainda era como instalar o localdb no cliente.
    Parabéns, esse tópico ajudou bastante.

    • andrealveslima disse:

      Maravilha, hein Anderson! Fico feliz por ter conseguido ajudar de alguma maneira com esse artigo.. Qualquer dificuldade é só entrar em contato..

      Abraço!
      André Lima

  • Manoel disse:

    Muito interessante e uma explicação abrangente. Obrigado e parabéns.

  • Feliphe disse:

    Parabéns mais uma vez, ótimo trabalho em que vem aplicando com conteúdo bastante interativo.

    • andrealveslima disse:

      Olá Feliphe, muito obrigado pelo comentário! Fico feliz que você tenha gostado desse artigo também.. Qualquer sugestão de outros temas ou dúvidas, é só entrar em contato..

      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 *