Aprenda como usar banco de dados local em seu app Windows 10

Quando desenvolvemos um aplicativo para desktop ou smartphone, cada vez mais procuramos manter os dados na nuvem. Mas ainda existem cenários que é necessário considerarmos manter os dados do aplicativo em um banco de dados local.

E nesse post iremos justamente tratar como podemos usar o SQLite como solução para manter os dados dentro do nosso aplicativo. Para tanto, vamos descrever os passos para preparar projetos para Universal Windows (Windows 10) mas que também podem ser aplicados a Universal Apps (Windows 8.1 e Windows Phone 8.1).

Para esse post utilizamos o Visual Studio 2015 Community que pode ser baixado gratuitamente pelo site https://www.visualstudio.com/pt-br/downloads/download-visual-studio-vs.aspx.

O código do exemplo pode ser obtido no GitHub do talkitbr e funciona tanto para Universal Apps como Universal Windows e foi baseado no código disponibilizado pela Microsoft em code.msdn.microsoft.com. Nesse post iremos destacar apenas parte do código contido no exemplo.

Etapa 1 – Instalando Extensões SQLite

Antes de iniciarmos o desenvolvimento do projeto, precisamos baixar as extensões SQLite do Visual Studio. São elas:

  • Para Windows 10: SQLite for Universal App Platform

  • Para Windows Phone 8.1: SQLite for Windows Phone 8.1

  • Para Windows 8.1: SQLite for Windows Runtime (Windows 8.1)

Para instalar as extensões, abra o Visual Studio e então acesse o item de menu Tools > Extensions and Updates.... Nele, selecione o item Online e então busque pelas extensões acima:

aprenda_usar_banco_dados_local_windows_10_add_extensions

Quando instalamos uma extensão, é exibido um sinal de checagem, como mostrado na imagem acima.

aprenda_usar_banco_dados_local_windows_10_add_reference

Uma vez instaladas as extensões, o próximo passo é adicionar as referências nos projetos. Selecione o item References do projeto no Solution Explorer e em seguida o item Add Reference....

Após aberta a janela com as referências do projeto, selecione Extensions dentro da categoria do projeto e depois a extensão que acabamos de instalar:

Adicionando extensão para projeto Universal Windows (Windows 10)
Adicionando extensão para projeto Universal Windows (Windows 10)

O mesmo pode ser feito para projetos Windows 8.1 e Windows Phone 8.1. Basta adicionar ao projeto a referência para a extensão compatível.

Etapa 2 – Adicionando pacotes NuGet

Agora vamos incluir pacotes NuGet que são a biblioteca SQLite.Net-PCL e o SQLiteExtensions. Esses pacotes estão disponíveis tanto para Windows 10 como Windows 8.1 e Windows Phone 8.1.

Para adicionar os pacotes, acesse o item de menu Tools > NuGet Package Manager > Manager Nuget Packages for Solution. Será aberta uma janela em que serão mostrados os pacotes instalados e também permitirá a busca de novos pacotes ou atualização de pacotes já instalados. Selecione a aba Browse e então busque por SQLite.Net. Selecione e instale os seguintes pacotes NuGet:

  • SQLite.Net.Async-PCL: para acessar arquivos de bancos de dados usando LINQ (Language Integrated Query).

  • SQLiteNetExtensions.Async: permite usar recursos ORM (Object Relational Mapping) como operações cascade, de relacionamento, entre outros.

aprenda_usar_banco_dados_local_windows_10_add_nuget

Etapa 3 – Criando as classes do nosso modelo

Temos todo ambiente pronto para começarmos a nossa solução. Vamos então criar as classes que representarão nossos dados no banco de dados local:

  • Classe Employee
using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;
using System.Collections.Generic;

namespace SQLiteModernApp.DataModel
{
    [Table("Employee")]
    public class Employee
    {
        [PrimaryKey, AutoIncrement]
        public int EmployeeId { get; set; }

        [MaxLength(30)]
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Email { get; set; }

        [ManyToMany(typeof(EmployeeDepartment), CascadeOperations = CascadeOperation.All)]
        public List<Department> Departments { get; set; }

        public Employee()
        {
            this.Departments = new List<Department>();
        }
    }
}
  • Classe Department
using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;
using System.Collections.Generic;

namespace SQLiteModernApp.DataModel
{
    [Table("Department")]
    public class Department
    {
        [PrimaryKey]
        public int DepartmentId { get; set; }

        [MaxLength(30)]
        public string DepartmentName { get; set; }        
    }
}
  • Classe de relacionamento EmployeeDepartment
using SQLiteNetExtensions.Attributes;

namespace SQLiteModernApp.DataModel
{
    class EmployeeDepartment
    {
        [ForeignKey(typeof(Employee))]
        public int EmployeeId { get; set; }

        [ForeignKey(typeof(Department))]
        public int DepartmentId { get; set; }
    }
}

Notem que há um relacionamento ManyToMany entre as classes e que é representada pela classe EmployeeDepartment.

Etapa 4 – Acessando o banco de dados

Está quase tudo pronto. Falta ainda escrever o código para criar o banco de dados (caso ainda não exista) e obter a conexão. Para isso precisamos informar o caminho onde o arquivo do banco de dados será gerado. Depois disso geramos as tabelas com base nas classes de modelo que criamos a pouco (só serão criadas caso ainda não existam). Crie a classe DBConnection conforme especificado abaixo:

using System.IO;
using System.Threading.Tasks;
using SQLiteModernApp.DataModel;
using SQLite.Net.Async;
using System;
using SQLite.Net;
using SQLite.Net.Platform.WinRT;

namespace SQLiteModernApp.DataAccess
{
    public class DbConnection : IDbConnection
    {
        string dbPath;
        SQLiteAsyncConnection conn;

        public DbConnection()
        {
            dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "Sample.sqlite");

            var connectionFactory = new Func<SQLiteConnectionWithLock>(() => new SQLiteConnectionWithLock(new SQLitePlatformWinRT(), new SQLiteConnectionString(dbPath, storeDateTimeAsTicks: false)));
            conn = new SQLiteAsyncConnection(connectionFactory);
        }

        public async Task InitializeDatabase()
        {
            await conn.CreateTableAsync<Department>();
            await conn.CreateTableAsync<Employee>();
            await conn.CreateTableAsync<EmployeeDepartment>();
        }

        public SQLiteAsyncConnection GetAsyncConnection()
        {
            return conn;
        }
    }
}

Agora vamos escrever as classes para isolar a forma como será feito o acesso aos dados. Segue por exemplo a classe EmployeeRepository:

using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite.Net.Async;
using SQLiteModernApp.DataAccess;
using SQLiteModernApp.DataModel;
using SQLiteNetExtensionsAsync.Extensions;

namespace SQLiteModernApp.Repository
{
    public class EmployeeRepository : IEmployeeRepository
    {
        SQLiteAsyncConnection conn;

        public EmployeeRepository(IDbConnection oIDbConnection)
        {
            conn = oIDbConnection.GetAsyncConnection();
        }

        public async Task InsertEmployeeAsync(Employee employee)
        {
            await conn.InsertOrReplaceWithChildrenAsync(employee);
        }

        public async Task UpdateEmployeeAsync(Employee employee)
        {
            await conn.UpdateWithChildrenAsync(employee);
        }

        public async Task DeleteEmployeeAsync(Employee employee)
        {
            await conn.DeleteAsync(employee);
        }

        public async Task<List<Employee>> SelectAllEmployeesAsync()
        {
            return await conn.GetAllWithChildrenAsync<Employee>();
        }

        public async Task<List<Employee>> SelectEmployeesAsync(string query)
        {
            return await conn.QueryAsync<Employee>(query);
        }
    }
}

No código acima demos destaque para as linhas que fazem acesso aos dados levando-se em conta os relacionamentos. Quando usados os métodos tipo WithChildren estamos incluindo também as classes relacionadas.

Etapa 5 – Integrando com o resto da aplicação

Está pronto o acesso ao banco de dados. Agora falta apenas integrar com a interface. No exemplo abaixo é tratado o evento para adicionar um novo Employee:

private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
    employee.Departments = new List<Department>();
    foreach (var item in cboDepartment.SelectedItems)
    {
        employee.Departments.Add((Department)item);
    }

    if (employee.EmployeeId == 0)
    {
        await oEmployeeRepository.InsertEmployeeAsync(employee);
    }
    else
    {
        await oEmployeeRepository.UpdateEmployeeAsync(employee);
    }

    Frame.GoBack();        
}

aprenda_usar_banco_dados_local_windows_10_running

Quer saber mais? Então continue nos acompanhando no blog talkitbr. Até a próxima!

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s