Xamarin.Forms Místní databáze
Databázový stroj SQLite umožňuje Xamarin.Forms aplikacím načítat a ukládat datové objekty ve sdíleném kódu. Ukázková aplikace používá k ukládání položek úkolů tabulku databáze SQLite. Tento článek popisuje, jak používat SQLite.Net ve sdíleném kódu k ukládání a načítání informací v místní databázi.
Integrujte SQLite.NET do mobilních aplikací pomocí následujícího postupu:
- Nainstalujte balíček NuGet.
- Konfigurujte konstanty.
- Vytvořte třídu přístupu k databázi.
- Přístup k datům v Xamarin.Forms.
- Pokročilá konfigurace.
Instalace balíčku NuGet SQLite
Pomocí správce balíčků NuGet vyhledejte sqlite-net-pcl a přidejte nejnovější verzi do projektu sdíleného kódu.
Existuje několik balíčků NuGet s podobnými názvy. Správný balíček má tyto atributy:
- ID: sqlite-net-pcl
- Autoři: SQLite-net
- Vlastníci: praeclarum
- Odkaz na NuGet: sqlite-net-pcl
I přes název balíčku použijte balíček NuGet sqlite-net-pcl i v projektech .NET Standard.
Důležité
SQLite.NET je knihovna třetí strany podporovaná z úložiště praeclarum/sqlite-net.
Konfigurace konstant aplikací
Ukázkový projekt obsahuje soubor Constants.cs , který poskytuje běžná konfigurační data:
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
{
get
{
var basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
return Path.Combine(basePath, DatabaseFilename);
}
}
}
Soubor konstant určuje výchozí SQLiteOpenFlag
hodnoty výčtu, které se používají k inicializaci připojení k databázi. Výčet SQLiteOpenFlag
podporuje tyto hodnoty:
Create
: Připojení automaticky vytvoří soubor databáze, pokud neexistuje.FullMutex
: Připojení se otevře v režimu serializovaného podprocesu.NoMutex
: Připojení se otevře v režimu více vláken.PrivateCache
: Připojení se nebude účastnit sdílené mezipaměti, i když je povolené.ReadWrite
: Připojení může číst a zapisovat data.SharedCache
: Připojení se bude účastnit sdílené mezipaměti, pokud je povolená.ProtectionComplete
: Soubor je zašifrovaný a nepřístupný, když je zařízení zamknuté.ProtectionCompleteUnlessOpen
: Soubor se zašifruje, dokud se neotevře, ale bude přístupný i v případě, že uživatel zařízení zamkne.ProtectionCompleteUntilFirstUserAuthentication
: Soubor se zašifruje, dokud uživatel zařízení nespustí a odemkne.ProtectionNone
: Soubor databáze není zašifrovaný.
V závislosti na způsobu použití databáze možná budete muset zadat různé příznaky. Další informace najdete v SQLiteOpenFlags
tématu Otevření nového připojení k databázi na sqlite.org.
Vytvoření třídy přístupu k databázi
Třída obálky databáze abstrahuje vrstvu přístupu k datům ze zbytku aplikace. Tato třída centralizuje logiku dotazů a zjednodušuje správu inicializace databáze, což usnadňuje refaktoring nebo rozšíření operací s daty při růstu aplikace. Aplikace Todo definuje TodoItemDatabase
třídu pro tento účel.
Opožděná inicializace
Používá TodoItemDatabase
asynchronní opožděnou inicializaci reprezentovanou vlastní AsyncLazy<T>
třídou ke zpoždění inicializace databáze, dokud nebude poprvé přístupná:
public class TodoItemDatabase
{
static SQLiteAsyncConnection Database;
public static readonly AsyncLazy<TodoItemDatabase> Instance = new AsyncLazy<TodoItemDatabase>(async () =>
{
var instance = new TodoItemDatabase();
CreateTableResult result = await Database.CreateTableAsync<TodoItem>();
return instance;
});
public TodoItemDatabase()
{
Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
}
//...
}
Pole Instance
slouží k vytvoření databázové tabulky pro TodoItem
objekt, pokud ještě neexistuje, a vrátí jako jednoúčelový TodoItemDatabase
. Pole Instance
typu AsyncLazy<TodoItemDatabase>
se sestaví při prvním čekání. Pokud se více vláken pokusí o přístup k poli současně, budou všechny používat jedinou konstrukci. Po dokončení stavby jsou všechny await
operace dokončeny. Kromě toho všechny await
operace po dokončení stavby budou pokračovat okamžitě, protože hodnota je k dispozici.
Poznámka:
Připojení k databázi je statické pole, které zajišťuje, aby se jednoúčelové připojení databáze používalo po dobu životnosti aplikace. Použití trvalého statického připojení nabízí lepší výkon než otevírání a zavírání připojení vícekrát během jedné relace aplikace.
Asynchronní opožděná inicializace
Aby bylo možné spustit inicializaci databáze, vyhnout se blokování provádění a mít možnost zachytit výjimky, ukázková aplikace používá asynchronní opožděné initalizace reprezentované AsyncLazy<T>
třídou:
public class AsyncLazy<T>
{
readonly Lazy<Task<T>> instance;
public AsyncLazy(Func<T> factory)
{
instance = new Lazy<Task<T>>(() => Task.Run(factory));
}
public AsyncLazy(Func<Task<T>> factory)
{
instance = new Lazy<Task<T>>(() => Task.Run(factory));
}
public TaskAwaiter<T> GetAwaiter()
{
return instance.Value.GetAwaiter();
}
}
Třída AsyncLazy
kombinuje Lazy<T>
a Task<T>
typy k vytvoření opožděné inicializované úlohy, která představuje inicializaci prostředku. Delegát továrny předaný konstruktoru může být synchronní nebo asynchronní. Delegáti továrny budou spuštěni ve vlákně fondu vláken a nebudou spuštěni více než jednou (i když se je více vláken pokusí spustit současně). Po dokončení delegáta továrny je k dispozici opožděná inicializovaná hodnota a všechny metody čekající na AsyncLazy<T>
instanci obdrží hodnotu. Další informace naleznete v tématu AsyncLazy.
Metody manipulace s daty
Třída TodoItemDatabase
obsahuje metody pro čtyři typy manipulace s daty: vytvoření, čtení, úpravy a odstranění. Knihovna SQLite.NET poskytuje jednoduchou relační mapu objektů (ORM), která umožňuje ukládat a načítat objekty bez psaní příkazů SQL.
public class TodoItemDatabase
{
// ...
public Task<List<TodoItem>> GetItemsAsync()
{
return Database.Table<TodoItem>().ToListAsync();
}
public Task<List<TodoItem>> GetItemsNotDoneAsync()
{
// SQL queries are also possible
return Database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
}
public Task<TodoItem> GetItemAsync(int id)
{
return Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();
}
public Task<int> SaveItemAsync(TodoItem item)
{
if (item.ID != 0)
{
return Database.UpdateAsync(item);
}
else
{
return Database.InsertAsync(item);
}
}
public Task<int> DeleteItemAsync(TodoItem item)
{
return Database.DeleteAsync(item);
}
}
Přístup k datům v Xamarin.Forms
Třída TodoItemDatabase
zveřejňuje Instance
pole, prostřednictvím kterého lze vyvolat operace přístupu k datům ve TodoItemDatabase
třídě:
async void OnSaveClicked(object sender, EventArgs e)
{
var todoItem = (TodoItem)BindingContext;
TodoItemDatabase database = await TodoItemDatabase.Instance;
await database.SaveItemAsync(todoItem);
// Navigate backwards
await Navigation.PopAsync();
}
Rozšířená konfigurace
SQLite poskytuje robustní rozhraní API s více funkcemi, než je popsáno v tomto článku a ukázkové aplikaci. Následující části se týkají funkcí, které jsou důležité pro škálovatelnost.
Další informace najdete v dokumentaci KQLite na sqlite.org.
Protokolování před zápisem
Ve výchozím nastavení používá SQLite tradiční deník vrácení zpět. Kopie nezměněného obsahu databáze se zapíše do samostatného souboru vrácení zpět a změny se zapíšou přímo do souboru databáze. Potvrzení nastane při odstranění deníku vrácení zpět.
Protokolování před zápisem (WAL) zapisuje změny do samostatného souboru WAL. V režimu WAL je commit speciální záznam, připojený k souboru WAL, který umožňuje více transakcí nastat v jednom souboru WAL. Soubor WAL se sloučí zpět do databázového souboru ve speciální operaci označované jako kontrolní bod.
Wal může být rychlejší pro místní databáze, protože čtenáři a zapisovače navzájem neblokují, což umožňuje souběžné operace čtení a zápisu. Režim WAL ale neumožňuje změny velikosti stránky, přidá do databáze další přidružení souborů a přidá další operaci vytváření kontrolních bodů.
Pokud chcete v SQLite.NET povolit WAL, zavolejte EnableWriteAheadLoggingAsync
metodu v SQLiteAsyncConnection
instanci:
await Database.EnableWriteAheadLoggingAsync();
Další informace najdete v tématu SQLite Write-Ahead Logging on sqlite.org.
Kopírování databáze
Existuje několik případů, kdy může být nutné zkopírovat databázi SQLite:
- Databáze byla dodána s vaší aplikací, ale musí být zkopírována nebo přesunuta do zapisovatelného úložiště na mobilním zařízení.
- Potřebujete vytvořit zálohu nebo kopii databáze.
- Potřebujete vytvořit verzi, přesunout nebo přejmenovat soubor databáze.
Obecně platí, že přesouvání, přejmenování nebo kopírování souboru databáze je stejný proces jako jakýkoli jiný typ souboru s několika dalšími aspekty:
- Před pokusem o přesunutí souboru databáze by se měla zavřít všechna připojení k databázi.
- Pokud použijete protokolování s předstihem, SQLite vytvoří soubor sdíleného přístupu k paměti (.shm) a (zapsat hlavičkový protokol) (.wal). Ujistěte se, že u těchto souborů použijete také všechny změny.
Další informace naleznete v tématu Zpracování souborů v Xamarin.Formssouboru .