Używanie SQLite.NET z systemem Android
Biblioteka SQLite.NET zalecana przez platformę Xamarin to bardzo podstawowa biblioteka ORM, która umożliwia łatwe przechowywanie i pobieranie obiektów w lokalnej bazie danych SQLite na urządzeniu z systemem Android. ORM to mapowanie relacyjne obiektów — interfejs API, który umożliwia zapisywanie i pobieranie "obiektów" z bazy danych bez konieczności pisania instrukcji SQL.
Aby uwzględnić bibliotekę SQLite.NET w aplikacji platformy Xamarin, dodaj następujący pakiet NuGet do projektu:
- Nazwa pakietu: sqlite-net-pcl
- Autor: Frank A. Krueger
- Identyfikator: sqlite-net-pcl
- Adres URL: nuget.org/packages/sqlite-net-pcl
Dostępnych jest wiele różnych pakietów SQLite — upewnij się, że wybrano prawidłowy (może to nie być najlepszy wynik w wyszukiwaniu).
Ważne
SQLite.NET to biblioteka innej firmy obsługiwana przez repozytorium praeclarum/sqlite-net.
Po udostępnieniu biblioteki SQLite.NET wykonaj następujące trzy kroki, aby uzyskać do niej dostęp do bazy danych:
Dodaj instrukcję using — dodaj następującą instrukcję do plików C#, w których wymagany jest dostęp do danych:
using SQLite;
Utwórz pustą bazę danych — można utworzyć odwołanie do bazy danych, przekazując ścieżkę pliku konstruktora klasy SQLiteConnection. Nie musisz sprawdzać, czy plik już istnieje — zostanie on utworzony automatycznie, jeśli jest to wymagane, w przeciwnym razie istniejący plik bazy danych zostanie otwarty. Zmienna
dbPath
powinna być określana zgodnie z regułami omówionymi wcześniej w tym dokumencie:var db = new SQLiteConnection (dbPath);
Zapisz dane — po utworzeniu obiektu SQLiteConnection polecenia bazy danych są wykonywane przez wywołanie jego metod, takich jak CreateTable i Insert w następujący sposób:
db.CreateTable<Stock> (); db.Insert (newStock); // after creating the newStock object
Pobieranie danych — aby pobrać obiekt (lub listę obiektów), użyj następującej składni:
var stock = db.Get<Stock>(5); // primary key id of 5 var stockList = db.Table<Stock>();
Przykład podstawowego dostępu do danych
Przykładowy kod DataAccess_Basic dla tego dokumentu wygląda następująco podczas uruchamiania w systemie Android. Kod ilustruje sposób wykonywania prostych operacji SQLite.NET i przedstawia wyniki w postaci tekstu w oknie głównym aplikacji.
Android
Poniższy przykładowy kod przedstawia całą interakcję z bazą danych przy użyciu biblioteki SQLite.NET w celu hermetyzacji dostępu do bazowej bazy danych. Pokazuje on:
Tworzenie pliku bazy danych
Wstawianie niektórych danych przez utworzenie obiektów, a następnie zapisanie ich
Wykonywanie zapytań dotyczących danych
Należy uwzględnić następujące przestrzenie nazw:
using SQLite; // from the github SQLite.cs class
Ostatni z nich wymaga dodania sqlite do projektu. Należy pamiętać, że tabela bazy danych SQLite jest definiowana przez dodanie atrybutów do klasy ( Stock
klasy) zamiast polecenia CREATE TABLE.
[Table("Items")]
public class Stock {
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
[MaxLength(8)]
public string Symbol { get; set; }
}
public static void DoSomeDataAccess () {
Console.WriteLine ("Creating database, if it doesn't already exist");
string dbPath = Path.Combine (
Environment.GetFolderPath (Environment.SpecialFolder.Personal),
"ormdemo.db3");
var db = new SQLiteConnection (dbPath);
db.CreateTable<Stock> ();
if (db.Table<Stock> ().Count() == 0) {
// only insert the data if it doesn't already exist
var newStock = new Stock ();
newStock.Symbol = "AAPL";
db.Insert (newStock);
newStock = new Stock ();
newStock.Symbol = "GOOG";
db.Insert (newStock);
newStock = new Stock ();
newStock.Symbol = "MSFT";
db.Insert (newStock);
}
Console.WriteLine("Reading data");
var table = db.Table<Stock> ();
foreach (var s in table) {
Console.WriteLine (s.Id + " " + s.Symbol);
}
}
Użycie atrybutu [Table]
bez określenia parametru nazwy tabeli spowoduje, że podstawowa tabela bazy danych będzie mieć taką samą nazwę jak klasa (w tym przypadku "Stock"). Rzeczywista nazwa tabeli jest ważna, jeśli zapytania SQL są zapisywane bezpośrednio w bazie danych, a nie przy użyciu metod dostępu do danych ORM. [Column("_id")]
Podobnie atrybut jest opcjonalny, a jeśli nie ma kolumny, zostanie dodana do tabeli o takiej samej nazwie jak właściwość w klasie.
Atrybuty SQLite
Typowe atrybuty, które można zastosować do klas w celu kontrolowania sposobu ich przechowywania w bazowej bazie danych, obejmują:
[PrimaryKey] — Ten atrybut można zastosować do właściwości całkowitej, aby wymusić na niej klucz podstawowy tabeli bazowej. Złożone klucze podstawowe nie są obsługiwane.
[AutoInkrementacja] — Ten atrybut spowoduje, że wartość właściwości całkowitej będzie automatycznie zwiększana dla każdego nowego obiektu wstawionego do bazy danych
[Column(name)] — Parametr
name
ustawia nazwę bazowej kolumny bazy danych.[Table(name)] — oznacza klasę jako możliwość przechowywania w bazowej tabeli SQLite o określonej nazwie.
[MaxLength(wartość)] — ogranicz długość właściwości tekstowej, gdy próba wstawienia bazy danych jest podejmowana. Użycie kodu powinno sprawdzić to przed wstawieniem obiektu, ponieważ ten atrybut jest sprawdzany tylko podczas próby wstawiania lub aktualizowania bazy danych.
[Ignoruj] — Powoduje, że SQLite.NET ignorować tę właściwość. Jest to szczególnie przydatne w przypadku właściwości o typie, którego nie można przechowywać w bazie danych, lub właściwościach, których nie można automatycznie rozpoznać za pomocą biblioteki SQLite.
[Unikatowe] — Gwarantuje, że wartości w bazowej kolumnie bazy danych są unikatowe.
Większość z tych atrybutów jest opcjonalna. Zawsze należy określić klucz podstawowy liczby całkowitej, aby zapytania dotyczące wybierania i usuwania mogły być wykonywane wydajnie na danych.
Bardziej złożone zapytania
Do wykonywania innych operacji danych można użyć następujących metod SQLiteConnection
:
Insert — dodaje nowy obiekt do bazy danych.
Get<T> — próbuje pobrać obiekt przy użyciu klucza podstawowego.
Tabela<T> — zwraca wszystkie obiekty w tabeli.
Delete — usuwa obiekt przy użyciu jego klucza podstawowego.
Zapytanie<T> — wykonaj zapytanie SQL zwracające liczbę wierszy (jako obiekty).
Execute — użyj tej metody (a nie
Query
), jeśli nie oczekujesz wierszy z powrotem z bazy danych SQL (takich jak instrukcje INSERT, UPDATE i DELETE).
Pobieranie obiektu za pomocą klucza podstawowego
SQLite.Net udostępnia metodę Get w celu pobrania pojedynczego obiektu na podstawie klucza podstawowego.
var existingItem = db.Get<Stock>(3);
Wybieranie obiektu przy użyciu linq
Metody zwracające kolekcje obsługują IEnumerable<T>
, aby można było używać linq do wykonywania zapytań lub sortowania zawartości tabeli. Poniższy kod przedstawia przykład użycia linq do odfiltrowania wszystkich wpisów rozpoczynających się literą "A":
var apple = from s in db.Table<Stock>()
where s.Symbol.StartsWith ("A")
select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);
Wybieranie obiektu przy użyciu języka SQL
Mimo że SQLite.Net może zapewnić dostęp oparty na obiektach do danych, czasami może być konieczne wykonanie bardziej złożonego zapytania niż zezwala linq (lub może być potrzebna szybsza wydajność). Polecenia SQL można używać z metodą Query, jak pokazano poniżej:
var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");
foreach (var s in stocksStartingWithA) {
Console.WriteLine ("a " + s.Symbol);
}
Uwaga
Podczas pisania instrukcji SQL bezpośrednio tworzysz zależność od nazw tabel i kolumn w bazie danych, które zostały wygenerowane na podstawie klas i ich atrybutów. Jeśli zmienisz te nazwy w kodzie, pamiętaj, aby zaktualizować wszelkie ręcznie napisane instrukcje SQL.
Usuwanie obiektu
Klucz podstawowy służy do usuwania wiersza, jak pokazano poniżej:
var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key
Możesz sprawdzić wartość , rowcount
aby potwierdzić, ile wierszy zostało dotkniętych (usuniętych w tym przypadku).
Używanie SQLite.NET z wieloma wątkami
SqLite obsługuje trzy różne tryby wątkowania: jednowątkowy, wielowątkowy i serializowany. Jeśli chcesz uzyskać dostęp do bazy danych z wielu wątków bez żadnych ograniczeń, możesz skonfigurować bibliotekę SQLite do korzystania z trybu wątkowania serializowanego. Ważne jest, aby ustawić ten tryb na wczesnym etapie aplikacji (na przykład na początku OnCreate
metody).
Aby zmienić tryb wątkowania, wywołaj metodę SqliteConnection.SetConfig
. Na przykład ten wiersz kodu konfiguruje sqlite dla trybu serializowanego :
using using Mono.Data.Sqlite;
...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);
Wersja sqlite systemu Android ma ograniczenie, które wymaga kilku kolejnych kroków. Jeśli wywołanie metody w celu SqliteConnection.SetConfig
utworzenia wyjątku SQLite, takiego jak library used incorrectly
, należy użyć następującego obejścia:
Połącz się z natywną biblioteką libsqlite.so , aby
sqlite3_shutdown
interfejsy API isqlite3_initialize
zostały udostępnione aplikacji:[DllImport("libsqlite.so")] internal static extern int sqlite3_shutdown(); [DllImport("libsqlite.so")] internal static extern int sqlite3_initialize();
Na początku
OnCreate
metody dodaj ten kod, aby zamknąć sqlite, skonfigurować go dla trybu serializowanego i ponownie zainicjować SQLite:using using Mono.Data.Sqlite; ... sqlite3_shutdown(); SqliteConnection.SetConfig(SQLiteConfig.Serialized); sqlite3_initialize();
To obejście działa również w przypadku Mono.Data.Sqlite
biblioteki. Aby uzyskać więcej informacji na temat sqlite i wielowątkowego, zobacz SQLite i Multiple Threads(Wiele wątków).