Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O mecanismo de banco de dados SQLite permite que aplicativos .NET Multi-platform App UI (.NET MAUI) carreguem e salvem objetos de dados em código compartilhado. Você pode integrar SQLite.NET em aplicativos .NET MAUI, para armazenar e recuperar informações em um banco de dados local, seguindo estas etapas:
- Instale o pacote NuGet.
- Configurar constantes.
- Crie a classe TodoItem.
- Criar uma classe de acesso ao banco de dados.
- Acessar dados.
- Configuração avançada.
Este artigo usa o pacote sqlite-net-pcl NuGet para fornecer acesso a uma tabela do banco de dados SQLite para armazenar tarefas pendentes. Uma alternativa é usar o pacote Microsoft.Data.Sqlite NuGet, que é um provedor de ADO.NET leve para SQLite. Microsoft.Data.Sqlite implementa as abstrações de ADO.NET comuns para funcionalidades como conexões, comandos e leitores de dados.
Instalar o pacote SQLite NuGet
Use o gerenciador de pacotes NuGet para procurar o pacote de sqlite-net-pcl
Há vários pacotes NuGet com nomes semelhantes. O pacote correto tem estes atributos:
- ID : sqlite-net-pcl
- Autores: SQLite-net
- proprietários: praeclarum
- Link do NuGet:sqlite-net-pcl
Apesar do nome do pacote, use o sqlite-net-pcl pacote NuGet em projetos .NET MAUI.
Importante
SQLite.NET é uma biblioteca de terceiros que é suportada a partir do praeclarum/sqlite-net repo.
Configurar constantes de aplicativo
Os dados de configuração, como nome de arquivo e caminho do banco de dados, podem ser armazenados como constantes em seu aplicativo. O projeto de exemplo inclui um arquivo de Constants.cs que fornece dados de configuração comuns:
public static class Constants
{
public const string DatabaseFilename = "TodoSQLite.db3";
public const SQLite.SQLiteOpenFlags Flags =
// open the database in read/write mode
SQLite.SQLiteOpenFlags.ReadWrite |
// create the database if it doesn't exist
SQLite.SQLiteOpenFlags.Create |
// enable multi-threaded database access
SQLite.SQLiteOpenFlags.SharedCache;
public static string DatabasePath =>
Path.Combine(FileSystem.AppDataDirectory, DatabaseFilename);
}
Neste exemplo, o arquivo de constantes especifica valores padrão SQLiteOpenFlag enum que são usados para inicializar a conexão do banco de dados. O SQLiteOpenFlag enum suporta estes valores:
-
Create: A conexão criará automaticamente o arquivo de banco de dados se ele não existir. -
FullMutex: A conexão é aberta no modo de encadeamento serializado. -
NoMutex: A conexão é aberta no modo multithreading. -
PrivateCache: A conexão não participará do cache compartilhado, mesmo que esteja habilitada. -
ReadWrite: A conexão pode ler e gravar dados. -
SharedCache: A conexão participará do cache compartilhado, se estiver habilitada. -
ProtectionComplete: O ficheiro está encriptado e inacessível enquanto o dispositivo está bloqueado. -
ProtectionCompleteUnlessOpen: O ficheiro é encriptado até ser aberto, mas fica acessível mesmo que o utilizador bloqueie o dispositivo. -
ProtectionCompleteUntilFirstUserAuthentication: O ficheiro é encriptado até que o utilizador tenha iniciado e desbloqueado o dispositivo. -
ProtectionNone: O ficheiro de base de dados não está encriptado.
Talvez seja necessário especificar sinalizadores diferentes, dependendo de como seu banco de dados será usado. Para obter mais informações sobre SQLiteOpenFlags, consulte Abrir uma Nova Conexão de Base de Dados no sqlite.org.
Criar classe TodoItem
Antes de codificar o acesso ao banco de dados, crie a classe que armazenará os dados.
public class TodoItem
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public bool Done { get; set; }
}
A ID nesta classe servirá como a chave primária que é incrementada automaticamente após salvar. Os atributos podem ser usados para especificar esse comportamento.
Criar uma classe de acesso ao banco de dados
Uma classe de wrapper de banco de dados abstrai a camada de acesso a dados do restante do aplicativo. Essa classe centraliza a lógica de consulta e simplifica o gerenciamento da inicialização do banco de dados, facilitando a refatoração ou expansão das operações de dados à medida que o aplicativo cresce. O aplicativo de exemplo define uma classe TodoItemDatabase para essa finalidade.
Inicialização lenta
O TodoItemDatabase usa inicialização lenta assíncrona para atrasar a inicialização do banco de dados até que ele seja acessado pela primeira vez, com um método Init simples que é chamado por cada método na classe:
public class TodoItemDatabase
{
SQLiteAsyncConnection database;
async Task Init()
{
if (database is not null)
return;
database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
var result = await database.CreateTableAsync<TodoItem>();
}
...
}
Métodos de manipulação de dados
A classe TodoItemDatabase inclui métodos para os quatro tipos de manipulação de dados: criar, ler, editar e excluir. A biblioteca SQLite.NET fornece um Mapa Relacional de Objetos (ORM) simples que permite armazenar e recuperar objetos sem escrever instruções SQL.
O exemplo a seguir mostra os métodos de manipulação de dados no aplicativo de exemplo:
public class TodoItemDatabase
{
...
public async Task<List<TodoItem>> GetItemsAsync()
{
await Init();
return await database.Table<TodoItem>().ToListAsync();
}
public async Task<List<TodoItem>> GetItemsNotDoneAsync()
{
await Init();
return await database.Table<TodoItem>().Where(t => t.Done).ToListAsync();
// SQL queries are also possible
//return await Database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
}
public async Task<TodoItem> GetItemAsync(int id)
{
await Init();
return await database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();
}
public async Task<int> SaveItemAsync(TodoItem item)
{
await Init();
if (item.ID != 0)
return await database.UpdateAsync(item);
else
return await database.InsertAsync(item);
}
public async Task<int> DeleteItemAsync(TodoItem item)
{
await Init();
return await database.DeleteAsync(item);
}
}
Dados de acesso
A classe TodoItemDatabase pode ser registrada como um singleton que pode ser usado em todo o aplicativo se você estiver usando a injeção de dependência. Por exemplo, você pode registrar suas páginas e a classe de acesso ao banco de dados como serviços no objeto IServiceCollection, em MauiProgram.cs, com os métodos AddSingleton e AddTransient:
builder.Services.AddSingleton<TodoListPage>();
builder.Services.AddTransient<TodoItemPage>();
builder.Services.AddSingleton<TodoItemDatabase>();
Esses serviços podem ser injetados automaticamente em construtores de classe e acessados:
TodoItemDatabase database;
public TodoItemPage(TodoItemDatabase todoItemDatabase)
{
InitializeComponent();
database = todoItemDatabase;
}
async void OnSaveClicked(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(Item.Name))
{
await DisplayAlert("Name Required", "Please enter a name for the todo item.", "OK");
return;
}
await database.SaveItemAsync(Item);
await Shell.Current.GoToAsync("..");
}
TodoItemDatabase database;
public TodoItemPage(TodoItemDatabase todoItemDatabase)
{
InitializeComponent();
database = todoItemDatabase;
}
async void OnSaveClicked(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(Item.Name))
{
await DisplayAlertAsync("Name Required", "Please enter a name for the todo item.", "OK");
return;
}
await database.SaveItemAsync(Item);
await Shell.Current.GoToAsync("..");
}
Como alternativa, novas instâncias da classe de acesso ao banco de dados podem ser criadas:
TodoItemDatabase database;
public TodoItemPage()
{
InitializeComponent();
database = new TodoItemDatabase();
}
Para obter mais informações sobre a injeção de dependência em aplicativos .NET MAUI, consulte Injeção de dependência.
Configuração avançada
O SQLite fornece uma API robusta com mais recursos do que os abordados neste artigo e no aplicativo de exemplo. As seções a seguir abordam os recursos que são importantes para a escalabilidade.
Para obter mais informações, consulte de documentação do SQLite no sqlite.org.
Registo de escrita antecipada
Por padrão, o SQLite usa um diário de reversão tradicional. Uma cópia do conteúdo inalterado do banco de dados é gravada em um arquivo de reversão separado e, em seguida, as alterações são gravadas diretamente no arquivo de banco de dados. O COMMIT ocorre quando o diário de reversão é eliminado.
Write-Ahead Log (WAL) grava as alterações em um arquivo WAL separado primeiro. No modo WAL, um COMMIT é um registro especial, anexado ao arquivo WAL, que permite que várias transações ocorram em um único arquivo WAL. Um arquivo WAL é mesclado novamente no arquivo de banco de dados em uma operação especial chamada ponto de verificação .
A WAL pode ser mais rápida para bancos de dados locais porque leitores e gravadores não bloqueiam uns aos outros, permitindo que as operações de leitura e gravação sejam simultâneas. No entanto, o modo WAL não permite alterações no tamanho da página, adiciona associações de ficheiros adicionais à base de dados e acrescenta a operação extra de verificação de ponto de controlo.
Para habilitar a WAL no SQLite.NET, chame o método EnableWriteAheadLoggingAsync na instância SQLiteAsyncConnection:
await Database.EnableWriteAheadLoggingAsync();
Para obter mais informações, consulte SQLite Write-Ahead Logging em sqlite.org.
Copiar um banco de dados
Há vários casos em que pode ser necessário copiar um banco de dados SQLite:
- Um banco de dados foi enviado com seu aplicativo, mas deve ser copiado ou movido para armazenamento gravável no dispositivo móvel.
- Você precisa fazer um backup ou cópia do banco de dados.
- Você precisa versionar, mover ou renomear o arquivo de banco de dados.
Em geral, mover, renomear ou copiar um arquivo de banco de dados é o mesmo processo que qualquer outro tipo de arquivo, com algumas considerações adicionais:
- Todas as conexões de banco de dados devem ser fechadas antes de tentar mover o arquivo de banco de dados.
- Se você usar Write-Ahead Log, o SQLite criará um arquivo de Acesso à Memória Compartilhada (.shm) e um arquivo (Write Ahead Log) (.wal). Certifique-se de aplicar quaisquer alterações a esses arquivos também.
Visualizar o exemplo