Использование SQLite.NET с Android

Библиотека SQLite.NET, которую рекомендует Xamarin, является очень простой ORM, которая позволяет легко хранить и извлекать объекты в локальной базе данных SQLite на устройстве Android. ORM означает сопоставление реляционных объектов — API, который позволяет сохранять и извлекать "объекты" из базы данных без написания инструкций SQL.

Чтобы включить библиотеку SQLite.NET в приложение Xamarin, добавьте следующий пакет NuGet в проект:

пакет NuGet SQLite.NET

Доступно несколько разных пакетов SQLite— обязательно выберите правильный (это может быть не лучший результат поиска).

Внимание

SQLite.NET — это сторонняя библиотека, поддерживаемая репозиторием praeclarum/sqlite-net.

Получив доступ к библиотеке SQLite.NET, выполните следующие три действия, чтобы использовать ее для доступа к базе данных:

  1. Добавьте инструкцию using. Добавьте следующую инструкцию в файлы C#, где требуется доступ к данным:

    using SQLite;
    
  2. Создание пустой базы данных — ссылка на базу данных может быть создана путем передачи пути к файлу конструктора класса SQLiteConnection. Вам не нужно проверять, существует ли файл, он будет автоматически создан при необходимости, в противном случае будет открыт существующий файл базы данных. Переменная dbPath должна быть определена в соответствии с правилами, описанными ранее в этом документе:

    var db = new SQLiteConnection (dbPath);
    
  3. Сохранение данных — после создания объекта SQLiteConnection команды базы данных выполняются путем вызова методов, таких как CreateTable и Insert, как показано ниже.

    db.CreateTable<Stock> ();
    db.Insert (newStock); // after creating the newStock object
    
  4. Получение данных — чтобы получить объект (или список объектов), используйте следующий синтаксис:

    var stock = db.Get<Stock>(5); // primary key id of 5
    var stockList = db.Table<Stock>();
    

Пример "Базовый доступ к данным"

Пример кода DataAccess_Basic для этого документа выглядит следующим образом при запуске в Android. В коде показано, как выполнять простые SQLite.NET операции и отображать результаты в виде текста в главном окне приложения.

Android

Пример SQLite.NET Android

В следующем примере кода показано все взаимодействие с базой данных с помощью библиотеки SQLite.NET для инкапсулировать доступ к базовой базе данных. В нем показано:

  1. Создание файла базы данных

  2. Вставка некоторых данных путем создания объектов и их сохранения

  3. Запрос данных

Вам потребуется включить эти пространства имен:

using SQLite; // from the github SQLite.cs class

Последний требует, чтобы вы добавили SQLite в проект. Обратите внимание, что таблица базы данных SQLite определяется путем добавления атрибутов в класс ( Stock класс), а не команды 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);
    }
}

[Table] Использование атрибута без указания параметра имени таблицы приведет к тому, что базовая таблица базы данных будет иметь то же имя, что и класс (в данном случае "Stock"). Фактическое имя таблицы важно, если вы записываете SQL-запросы непосредственно в базу данных, а не используете методы доступа к данным ORM. Аналогичным образом [Column("_id")] атрибут является необязательным, и если столбец отсутствует, он будет добавлен в таблицу с тем же именем, что и свойство в классе.

Атрибуты SQLite

Общие атрибуты, которые можно применить к классам, чтобы управлять тем, как они хранятся в базовой базе данных, включают:

  • [PrimaryKey] — этот атрибут можно применить к целочисленным свойству, чтобы принудительно использовать его в качестве первичного ключа базовой таблицы. Составные первичные ключи не поддерживаются.

  • [AutoIncrement] — этот атрибут приведет к автоматическому добавлению значения целочисленного свойства для каждого нового объекта, вставленного в базу данных.

  • [Столбец(имя)] — параметр name задает имя базового столбца базы данных.

  • [Table(name)] — помечает класс как возможность храниться в базовой таблице SQLite с указанным именем.

  • [MaxLength(value)] — ограничить длину текстового свойства при попытке вставки базы данных. Использование кода должно проверить это перед вставкой объекта, так как этот атрибут проверяется только при попытке вставки или обновления базы данных.

  • [Игнорировать] — вызывает SQLite.NET игнорировать это свойство. Это особенно полезно для свойств, имеющих тип, который не может храниться в базе данных, или свойства, которые не могут быть разрешены автоматически с помощью SQLite.

  • [Уникальный] — гарантирует, что значения в базовом столбце базы данных уникальны.

Большинство этих атрибутов являются необязательными. Всегда следует указать целый первичный ключ, чтобы запросы на выбор и удаление могли эффективно выполняться в данных.

Более сложные запросы

Для выполнения других операций с данными можно использовать следующие методы SQLiteConnection :

  • Вставка — добавляет новый объект в базу данных.

  • Получение<T> — пытается получить объект с помощью первичного ключа.

  • Таблица<T> — возвращает все объекты в таблице.

  • Delete — удаляет объект с помощью первичного ключа.

  • Запрос<T> . Выполнение SQL-запроса, возвращающего ряд строк (в виде объектов).

  • Выполнение — используйте этот метод (и не Query), если строки не ожидаются из SQL (например, инструкции INSERT, UPDATE и DELETE).

Получение объекта первичным ключом

SQLite.Net предоставляет метод Get для получения одного объекта на основе его первичного ключа.

var existingItem = db.Get<Stock>(3);

Выбор объекта с помощью Linq

Методы, возвращающие поддержку IEnumerable<T> коллекций, чтобы использовать Linq для запроса или сортировки содержимого таблицы. В следующем коде показан пример с помощью Linq для фильтрации всех записей, начинающихся с буквы "A":

var apple = from s in db.Table<Stock>()
    where s.Symbol.StartsWith ("A")
    select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);

Выбор объекта с помощью SQL

Несмотря на то, что SQLite.Net могут предоставлять доступ на основе объектов к данным, иногда может потребоваться выполнить более сложный запрос, чем Linq допускает (или может потребоваться более быстрая производительность). Команды SQL можно использовать с методом query, как показано ниже:

var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");
foreach (var s in stocksStartingWithA) {
    Console.WriteLine ("a " + s.Symbol);
}

Примечание.

При написании инструкций SQL непосредственно создается зависимость от имен таблиц и столбцов в базе данных, созданных из классов и их атрибутов. При изменении этих имен в коде необходимо не забудьте обновить все написанные вручную инструкции SQL.

Удаление объекта

Первичный ключ используется для удаления строки, как показано ниже:

var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key

Вы можете проверить rowcount , сколько строк было затронуты (удалено в этом случае).

Использование SQLite.NET с несколькими потоками

SQLite поддерживает три разных режима потоков: однопотоковый, многопоточный и сериализованный. Если вы хотите получить доступ к базе данных из нескольких потоков без каких-либо ограничений, можно настроить SQLite для использования режима сериализованной потоковой передачи. Важно задать этот режим в начале приложения (например, в начале OnCreate метода).

Чтобы изменить режим потоковой передачи, вызовите SqliteConnection.SetConfig. Например, эта строка кода настраивает SQLite для сериализованного режима:

using using Mono.Data.Sqlite;
...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);

В версии Android SQLite есть ограничение, которое требует выполнения нескольких действий. Если вызов создает SqliteConnection.SetConfig исключение SQLite, например library used incorrectly, необходимо использовать следующее решение:

  1. Ссылка на собственную библиотеку libsqlite.so таким образом, чтобы sqlite3_shutdown api и sqlite3_initialize интерфейсы API были доступны для приложения:

    [DllImport("libsqlite.so")]
    internal static extern int sqlite3_shutdown();
    
    [DllImport("libsqlite.so")]
    internal static extern int sqlite3_initialize();
    
  2. В самом начале OnCreate метода добавьте этот код для завершения работы SQLite, настройте его для сериализованного режима и повторно инициализируйте SQLite:

    using using Mono.Data.Sqlite;
    ...
    sqlite3_shutdown();
    SqliteConnection.SetConfig(SQLiteConfig.Serialized);
    sqlite3_initialize();
    

Это решение также работает для библиотеки Mono.Data.Sqlite . Дополнительные сведения о SQLite и нескольких потоках см. в разделе SQLite и нескольких потоков.