Compartilhar via


Tutorial: Usar um banco de dados SQLite em um aplicativo Windows

SQLite fornece uma solução de banco de dados leve e confiável para armazenar dados localmente em aplicativos Windows. Ao contrário dos sistemas de banco de dados tradicionais que exigem instalações de servidor separadas e configurações complexas, o SQLite é executado inteiramente em seu processo de aplicativo e armazena dados em um único arquivo no dispositivo do usuário.

Este tutorial mostra como integrar o SQLite ao aplicativo WinUI usando as bibliotecas de acesso a dados recomendadas da Microsoft. Você aprenderá a configurar um banco de dados, criar tabelas e implementar operações de dados básicas, tudo isso seguindo as práticas recomendadas de segurança para proteger contra vulnerabilidades comuns.

O que você vai realizar

Neste tutorial, você aprenderá como:

  • Configurar seu aplicativo Windows para usar o SQLite com a biblioteca Microsoft.Data.SQLite
  • Criar e inicializar um banco de dados local
  • Implementar métodos seguros de inserção e recuperação de dados
  • Criar uma interface do usuário simples para interagir com seus dados

Pré-requisitos

Para concluir este tutorial, você precisará:

  • Visual Studio 2022 ou posterior com Desenvolvimento de aplicativos WinUI carga de trabalho
  • Familiaridade básica com C# e XAML
  • Noções básicas sobre conceitos fundamentais do banco de dados

Principais melhorias que essa abordagem oferece

O uso do SQLite para armazenamento de dados local em seu aplicativo Windows oferece várias vantagens:

  • Implantação simplificada: não é necessária nenhuma instalação separada do servidor de banco de dados
  • Segurança aprimorada: os dados permanecem locais no dispositivo do usuário
  • Desempenho aprimorado: o acesso direto a arquivos elimina a latência de rede
  • Complexidade reduzida: o banco de dados de arquivo único simplifica o backup e a migração

As técnicas que você aprenderá a aplicar a qualquer aplicativo Windows que precise armazenar dados estruturados localmente, desde o armazenamento de configurações simples até cenários complexos de gerenciamento de dados.

Dica

Você pode usar a assistência de IA para ajudar a evitar ataques de injeção de SQL no SQLite.

Benefícios do SQLite para armazenamento local

✔️ O SQLite é leve e independente. É uma biblioteca de código sem nenhuma outra dependência. Não há nada para configurar.

✔️ Não há nenhum servidor de banco de dados. O cliente e o servidor são executados no mesmo processo.

✔️ O SQLite é de domínio público, então você pode usá-lo livremente e distribuí-lo com seu aplicativo.

✔️ O SQLite funciona em várias arquiteturas e plataformas.

Você pode ler mais sobre o SQLite aqui.

Escolher uma camada de abstração

Recomendamos que você use Entity Framework Core ou a biblioteca SQLite de software livre criada pela Microsoft.

Entity Framework Core

O EF (Entity Framework) é um mapeador relacional de objeto que pode ser usado para trabalhar com os dados relacionais usando objetos específicos de domínio. Se você já tiver usado essa estrutura para trabalhar com dados em outros aplicativos .NET, poderá usar o mesmo código em seu aplicativo WinUI e ele funcionará com as alterações apropriadas no connection string.

Para experimentar, confira Introdução com EF Core.

Biblioteca SQLite

A biblioteca Microsoft.Data.Sqlite implementa as interfaces no namespace System.Data.Common. A Microsoft mantém ativamente essas implementações e elas fornecem um wrapper intuitivo em torno da API do SQLite nativo de baixo nível.

O restante deste guia ajuda você a usar essa biblioteca.

Configurar sua solução para usar a biblioteca Microsoft.Data.SQLite

Começaremos com um projeto WinUI básico e, em seguida, instalaremos o pacote NuGet do SQLite. Consulte Criar um aplicativo WinUI para obter instruções sobre como criar seu primeiro projeto WinUI.

Todas as versões com suporte do Windows dão suporte ao SQLite, portanto, seu aplicativo não precisa empacotar bibliotecas SQLite. Em vez disso, seu aplicativo pode usar a versão do SQLite que vem instalada com Windows. Isso ajuda você de algumas maneiras.

✔️ Reduz o tamanho do aplicativo, pois você não precisa baixar o binário do SQLite e empacotá-lo como parte do aplicativo.

✔️ Impede que você precise efetuar push de uma nova versão do aplicativo para os usuários no caso de a SQLite publicar correções críticas para bugs e vulnerabilidades de segurança no SQLite. A versão Windows do SQLite é mantida pela Microsoft em coordenação com SQLite.org.

✔️ O tempo de carregamento do aplicativo tem o potencial de ser mais rápido porque, provavelmente, a versão do SDK do SQLite já será carregada na memória.

Para começar, adicione ao projeto uma classe chamada DataAccess. Se você planeja compartilhar sua lógica de acesso a dados com outro código do cliente, pode usar um projeto de biblioteca de classes .NET para conter seu código de acesso a dados, mas não usaremos um em nosso exemplo.

  1. Clique com o botão direito do mouse na solução e clique em Gerenciar pacotes NuGet para solução.

    A captura de tela do Solution Explorer do Visual Studio com o projeto clicado com o botão direito do mouse e a opção Gerenciar Pacotes NuGet realçada.

    Neste ponto, você tem uma opção. Você pode usar a versão do SQLite incluída com Windows ou se você tiver algum motivo para usar uma versão específica do SQLite, poderá incluir a biblioteca SQLite em seu pacote. Vamos usar a versão do SQLite incluída com Windows.

  2. Escolha a guia Procurar, procure o pacote Microsoft.Data.SQLite e instale a versão estável mais recente.

    SQLite Pacote NuGet

Adicionar e recuperar dados em um banco de dados do SQLite

Vamos fazer o seguinte:

1️⃣ Preparar a classe de acesso a dados.

2️⃣ Inicializar o banco de dados SQLite.

3️⃣ Inserir dados no banco de dados do SQLite.

4️⃣ Recuperar dados do banco de dados SQLite.

5️⃣ Adicionar uma interface do usuário básica.

Preparar a classe de acesso a dados

Abra a classe DataAccess no projeto e faça com que ela seja estática.

Observação

Embora o exemplo coloque o código de acesso a dados em uma classe estática, essa é uma opção de design e é completamente opcional.

public static class DataAccess
{
}

Adicione as declarações using a seguir ao início deste arquivo.

using Microsoft.Data.Sqlite;
using System.Collections.Generic;

Inicializar o banco de dados SQLite

Adicione um método à classe DataAccess que inicialize o banco de dados SQLite.

public async static void InitializeDatabase()
{ 
    await ApplicationData.Current.LocalFolder
            .CreateFileAsync("sqliteSample.db", CreationCollisionOption.OpenIfExists);
    string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
                                 "sqliteSample.db");
    using (var db = new SqliteConnection($"Filename={dbpath}"))
    {
        db.Open();

        string tableCommand = "CREATE TABLE IF NOT " +
            "EXISTS MyTable (Primary_Key INTEGER PRIMARY KEY, " +
            "Text_Entry NVARCHAR(2048) NULL)";

        var createTable = new SqliteCommand(tableCommand, db);

        createTable.ExecuteReader();
    }
}

Observação

O código acima que utiliza membros ApplicationData funcionará apenas para aplicativos empacotados que estejam rodando dentro de um contêiner de aplicativos. Todos os outros aplicativos Windows devem acessar membros ApplicationData por meio da classe ApplicationDataManager.

Este código cria o banco de dados SQLite e o armazena no armazenamento de dados local do aplicativo.

Neste exemplo, nomeamos o banco de dados sqlliteSample.db, mas você pode usar qualquer nome que desejar, desde que use esse nome em todos os objetos SqliteConnection em que criar uma instância. Em um aplicativo de produção, as informações de conexão, como o nome do arquivo de banco de dados, devem ser armazenadas na configuração do aplicativo em vez de escritas diretamente (consulte Adicionando a Configuração do Aplicativo Azure usando Serviços Conectados do Visual Studio).

No construtor do arquivo App.xaml.cs do projeto, chame o método InitializeDatabase da classe DataAccess. Isso garantirá que o banco de dados seja criado ou aberto sempre que o aplicativo for iniciado.

public App()
{
    this.InitializeComponent();

    DataAccess.InitializeDatabase();
}

Inserir dados no banco de dados do SQLite

Adicione um método à classe DataAccess que insira dados no banco de dados SQLite. Este código usa parâmetros na consulta para evitar ataques de injeção do SQL.

public static void AddData(string inputText)
{
    string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
                                 "sqliteSample.db");
    using (var db = new SqliteConnection($"Filename={dbpath}"))
    {
        db.Open();

        var insertCommand = new SqliteCommand();
        insertCommand.Connection = db;

        // Use parameterized query to prevent SQL injection attacks
        insertCommand.CommandText = "INSERT INTO MyTable VALUES (NULL, @Entry);";
        insertCommand.Parameters.AddWithValue("@Entry", inputText);

        insertCommand.ExecuteReader();
    }

}

Recuperar dados do banco de dados SQLite

Adicione um método que obtenha todas as linhas de dados de uma tabela no banco de dados SQLite.

public static List<string> GetData()
{
    var entries = new List<string>();
    string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
                                 "sqliteSample.db");
    using (var db = new SqliteConnection($"Filename={dbpath}"))
    {
        db.Open();
        var selectCommand = new SqliteCommand
            ("SELECT Text_Entry from MyTable", db);

        SqliteDataReader query = selectCommand.ExecuteReader();

        while (query.Read())
        {
            entries.Add(query.GetString(0));
        }
    }

    return entries;
}

O método Leitura avança por linhas de dados retornados. Ele retornará true se houver mais linhas restantes; caso contrário, retornará false.

O método GetString retorna o valor da coluna especificada como uma cadeia de caracteres. Ele aceita um valor inteiro que representa o ordinal da coluna baseada em zero dos dados que você deseja. Você pode usar métodos semelhantes, como GetDataTime e GetBoolean. Escolha um método com base em qual tipo de dados a coluna contém.

O parâmetro ordinal não é tão importante neste exemplo porque estamos selecionando todas as entradas em uma única coluna. No entanto, se várias colunas fizerem parte da sua consulta, use o valor ordinal para obter a coluna da qual você deseja obter dados.

Adicionar uma interface do usuário básica

No arquivo MainWindow.xaml do projeto, adicione o XAML a seguir.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBox x:Name="Input_Box"/>
        <Button Click="AddData">Add</Button>
        <ListView x:Name="Output">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</Grid>

Essa interface do usuário básica dá ao usuário um TextBox que pode ser usado para digitar uma cadeia de caracteres que adicionaremos ao banco de dados SQLite. Conectaremos o Button nessa interface do usuário a um manipulador de eventos que recuperará dados do banco de dados SQLite e, em seguida, mostrará esses dados no ListView.

No arquivo MainWindow.xaml.cs, adicione o manipulador a seguir. Este é o método que associamos ao evento Click do Button na interface do usuário.

private void AddData(object sender, RoutedEventArgs e)
{
    DataAccess.AddData(Input_Box.Text);

    Output.ItemsSource = DataAccess.GetData();
}

Também queremos ter certeza de que todos os dados existentes sejam carregados quando o aplicativo for iniciado. Adicione uma linha de código ao construtor MainWindow para chamar GetData().

public MainWindow()
{
    this.InitializeComponent();

    Output.ItemsSource = DataAccess.GetData();
}

Isso é tudo. Explore o Microsoft.Data.Sqlite para ver o que mais você pode fazer com o banco de dados SQLite. Confira os links abaixo para saber mais sobre outras maneiras de usar dados em seus aplicativos Windows.

Evitar ataques de injeção de SQL

O código neste exemplo usa consultas parametrizadas para evitar ataques de injeção de SQL. Nunca concatene a entrada do usuário em uma cadeia de caracteres de consulta SQL. Sempre use parâmetros. Você pode pedir a Copilot mais dicas sobre como evitar ataques de injeção de SQL.

O texto a seguir mostra um exemplo de prompt para Copilot:

Can you provide some best practices to avoid SQL injection attacks when writing SQLite queries in C# code?

Copilot é alimentado pela IA, portanto, surpresas e erros são possíveis. Para obter mais informações, consulte Copilot perguntas frequentes.

Conectar seu aplicativo diretamente a um banco de dados SQL Server

Consulte Use um banco de dados SQL Server em um aplicativo Windows.

Compartilhar código entre aplicativos diferentes em diferentes plataformas

Veja "Compartilhar código entre a área de trabalho e a UWP".

Adicionar páginas modelo mestre-detalhe com back-end SQL do Azure

Consulte o exemplo de banco de dados de pedidos de clientes.