Como usar base de dados SQLite em Windows 10 Universal Apps

Âmbito

Este artigo tem como objetivo mostrar como usar uma base de dados SQLite em Windows 10 Universal Apps, mais especificamente ligação à base de dados, obtenção e persistência de dados.

Introdução

Hoje em dia qualquer aplicação tem como requisito o uso de base de dados para armazenar os dados, desta forma existem várias soluções relacionais ou não, para o efeito. Uma solução muito usada nas aplicações móveis é o uso de base de dados SQLite, uma vez que é uma solução simples e fácil de usar. Em Windows 10 Universal Apps é possível usar base de dados SQLite, que atualmente se encontra numa versão preview, e que pode sofrer alterações até sair a versão final.

É sabido que a Entity Framework 7 irá suportar o Windows 10 Universal apps, no entanto este artigo não irá usar esta solução e será usada a biblioteca SQLite.Net-PCL, uma vez que é atualmente uma das bibliotecas mais simples de usar, e cujo código fonte está disponível no GitHub.

Nota: Este artigo foi escrito usando a versão Windows 10 Technical Preview Build 10240

Versão do Windows 10
Figura 1: Versão do Windows 10

e a Technical Preview Tools version 10.0.10069.

Versão do Technical Preview Tools
Figura 2: Versão do Technical Preview Tools

Descrição

Comecemos por criar uma Windows 10 Universal app, como podemos ver na figura 3:

Criação de Windows 10 Universal App
Figura 3: Criação de Windows 10 Universal App

Cujo resultado será

Solução de uma aplicação Windows 10 Universal
Figura 4: Solução de uma aplicação Windows 10 Universal

Para os mais novatos em Windows 10 Universal apps é preciso ter atenção que deixamos de desenvolver aplicações para cada plataforma, e passamos a ter uma única aplicação que irá correr nas várias plataformas, por esta razão passamos a ter apenas um projeto na solução. Para dar suporte a funcionalidades específicas de cada plataforma passamos a ter disponíveis as extensões, que só irão estar disponível na respetiva plataforma para o qual foram fornecida.

Modelo de dados

Uma vez que temos o projeto criado, agora devemos criar o modelo de dados que define os dados a persistir pela aplicação na base de dados SQLite. Desta forma, para ajudar a construir o exemplo iremos usar um dos datasets fornecido pelo http://www.cityofboston.gov/, mais especificamente o dataset https://data.cityofboston.gov/resource/4swk-wcg8.json.

Sendo assim, iremos ter uma classe chamada BostonEmployee, que é definida por

public class BostonEmployee
    {
        public string Name { get; set }

        public string Title { get; set; }

        [JsonProperty(PropertyName = "department_name")]
        public string DepartmentName { get; set; }

        public double Regular { get; set; }

        [JsonProperty(PropertyName = "total_earnings")]
        public string TotalEarnings { get; set; }

        public double Value { get; set; }

        public string Zip { get; set; }

        public string Detail { get; set; }

        public string Injured { get; set; }

        public string Other { get; set; }

        public string Retro { get; set; }

        public string Overtime { get; set; }

        public string Quinn { get; set; }
    }

Nota: É requisito instalar o NuGet Json.net (Figura 5) uma vez que é alterado o nome das propriedades em relação ao JSON recebido, de forma a se ter uma leitura mais legível.

Instalação do NuGet Json.Net
Figura 5: Instalação do NuGet Json.Net

O consumo dos dados será um pedido HTTP, muito simples, como podemos ver de seguida:

public class WebServiceManager
    {
        public async Task GetBostonEmployeesEarnings()
        {
            string url = "https://data.cityofboston.gov/resource/4swk-wcg8.json";
            
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get, new Uri(url));

            // Send the registration request.
            var response = await client.SendAsync(request);
            var message = await response.Content.ReadAsStringAsync();
            var employees = JsonConvert.DeserializeObject(message);
            return employees;
        }
    }

Usando SQLite

Instalação

Para podermos usar base de dados SQLite é necessário instalar o vsix fornecido no site oficial da SQLite: http://sqlite.org/download.html, atualmente em versão preview (Figura 6) e adicionar as respetivas referências (Figura 7 e 8):

Obtenção do SQLIte para UAP (sqlite-uap-201504202353.vsix)
Figura 6: Obtenção do SQLIte para UAP (sqlite-uap-201504202353.vsix)
Adicionar referências
Figura 7: Adicionar referências
Referências da aplicação
Figura 8: Referências da aplicação

Portanto, neste momento temos o SQLite instalado e as referências foram adicionadas ao projeto, falta agora instalar o NuGet SQLite.Net-PCL (Figura 9), que é uma biblioteca que irá facilitar a criação e conexão à base de dados, assim como na gestão de dados. Este NuGet irá adicionar as seguintes referências:

  • Net
  • Net.Platform.WinRT
Instalação do NuGet SQLite.Net-PCL
Figura 9: Instalação do NuGet SQLite.Net-PCL

Criação da base de dados

Antes de criarmos a base de dados é necessário definir o percurso da base de dados, isto é, o local onde a base de dados vai ser guardada.  Este percurso irá ser utilizados em futuros acessos à base de dados, desta forma podemos definir o databasePath no constructor:

private string _dataBasePath;

        public MainPage()
        {
           InitializeComponent();
            _dataBasePath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
        }

De seguida devemos alterar a classe BostonEmployee de forma a definir a PrimaryKey:

[PrimaryKey]
public string Name { get; set; }

E depois podemos então aceder à base de dados, para podermos criar a tabela referente ao BostonEmployee:

public void CreateDatabase()
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                conn.CreateTable();
            }
        }

Gestão de dados

Uma vez que já criamos a base de dados, agora podemos inserir, apagar e alterar os dados da mesma, para isso devemos usar o SQLiteConnection que terá todos os métodos necessários para efetuar as operações CRUD:

Inserir

   public void SaveData(BostonEmployee bostonEmployee)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                conn.Insert(bostonEmployee);
                conn.Commit();
            }
        }

        public void SaveData(IEnumerable bostonEmployees)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                conn.InsertAll(bostonEmployees);
                conn.Commit();
            }
        }

Obter

Para obter o BostonEmployee usando o Name, podemos efectuar:

public BostonEmployee GetByName(string name)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                return conn.Get(name);
            }
        }

Para obter BostonEmployees baseadas numa pesquisa ao Title, podemos efectuar:

   public BostonEmployee GetBostonEmployee(string title)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                return conn.Get(i=>i.Title.Equals(title));
            }
        }

Para fazer paginação sobre os dados, podemos efectuar:

public IEnumerable Pagination(int numToSkip, int numToTake)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
               return conn.Table().Skip(numToSkip).Take(numToTake);
            }
        }

Para fazer queries SQL, podemos efectuar:

   private string sqlquery = "SELECT * FROM [BostonEmployee] WHERE [Value] = 0.0";

        public IEnumerable  SQLQuery(string sqlquery)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                return conn.Query(sqlquery);
            }
        }

Nota: É de notar que é possível usar os vários métodos fornecidos pelo Linq, que permitirá efetuar diferentes queries à tabela em causa, assim como usar queries em SQL.

Apagar
public void DeleteData(BostonEmployee bostonEmployee)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                conn.Delete(bostonEmployee);
                conn.Commit();
            }
        }
Alterar
public void UpdateData(BostonEmployee bostonEmployee)
        {
            using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), _dataBasePath))
            {
                conn.Update(bostonEmployee);
                conn.Commit();
            }
        }

Conclusão

Em conclusão podemos verificar que o uso de base de dados em Windows 10 Universal Apps é simples, e o uso de base de dados SQLite é atualmente uma das soluções disponível (em versão preview), cuja implementação não difere em muito do uso em aplicações WinRT. Sendo muito simples criar e efetuar as operações CRUD usando a biblioteca SQLite.Net-PCL.