Android での SQLite.NET の使用

Xamarin が推奨する SQLite.NET ライブラリは、Android デバイス上のローカル SQLite データベースにオブジェクトを簡単に格納および取得できる非常に基本的な ORM です。 ORM はオブジェクト リレーショナル マッピングの略です。SQL ステートメントを記述せずにデータベースから "オブジェクト" を保存して取得できる API です。

Xamarin アプリに SQLite.NET ライブラリを含めるには、次の NuGet パッケージをプロジェクトに追加します。

NuGet パッケージ SQLite.NET NuGet パッケージ

使用できるさまざまな SQLite パッケージが多数あります。必ず正しいものを選択してください (検索の上位の結果ではない可能性があります)。

重要

SQLite.NET は、praeclarum/sqlite-net リポジトリからサポートされているサードパーティ製ライブラリです。

SQLite.NET ライブラリを使用できるようになったら、次の 3 つの手順に従ってデータベースにアクセスします。

  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

Android SQLite.NET サンプル

次のコード サンプルは、SQLite.NET ライブラリを使用して基になるデータベース アクセスをカプセル化するデータベース全体の相互作用を示しています。 次の情報が表示されます。

  1. データベース ファイルの作成

  2. オブジェクトを作成して保存してデータを挿入する

  3. データのクエリ

次の名前空間を含める必要があります。

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

最後の 1 つは、SQLite をプロジェクトに追加している必要があります。 SQLite データベース テーブルは、CREATE TABLE コマンドではなくクラス (クラス) に属性を Stock 追加することによって定義されることに注意してください。

[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") と同じになります。 実際のテーブル名は、ORM データ アクセスメソッドを使用するのではなく、データベースに対して SQL クエリを直接記述する場合に重要です。 同様に、 [Column("_id")] 属性は省略可能であり、存在しない場合は、 クラスの プロパティと同じ名前の列がテーブルに追加されます。

SQLite 属性

基になるデータベースへの格納方法を制御するためにクラスに適用できる一般的な属性は次のとおりです。

  • [PrimaryKey] – この属性を整数プロパティに適用して、基になるテーブルの主キーにすることができます。 複合主キーはサポートされていません。

  • [AutoIncrement] – この属性により、データベースに挿入された新しいオブジェクトごとに、整数プロパティの値が自動的にインクリメントされます

  • [Column(name)] – パラメーターは name 、基になるデータベース列の名前を設定します。

  • [Table(name)] – 名前を指定して、基になる SQLite テーブルに格納できることをクラスにマークします。

  • [MaxLength(value)] – データベースの挿入が試行されたときに、テキスト プロパティの長さを制限します。 データベースの挿入または更新操作が試行された場合にのみ、この属性が 'checked' であるため、オブジェクトを挿入する前に、コードを使用してこれを検証する必要があります。

  • [無視] – SQLite.NET がこのプロパティを無視します。 これは、データベースに格納できない型を持つプロパティや、SQLite で自動的に解決できないコレクションをモデル化するプロパティに特に便利です。

  • [一意] – 基になるデータベース列の値が一意であることを確認します。

これらの属性のほとんどは省略可能です。 選択クエリと削除クエリをデータに対して効率的に実行できるように、常に整数の主キーを指定する必要があります。

より複雑なクエリ

の次のメソッドを SQLiteConnection 使用して、他のデータ操作を実行できます。

  • Insert – データベースに新しいオブジェクトを追加します。

  • 取得<T> – 主キーを使用してオブジェクトの取得を試みます。

  • テーブル<T> – テーブル内のすべてのオブジェクトを返します。

  • Delete – 主キーを使用してオブジェクトを削除します。

  • クエリ<T> – (オブジェクトとして) 多数の行を返す SQL クエリを実行します。

  • Execute – SQL から行が戻る必要がない場合 (INSERT、UPDATE、DELETE 命令など) には、このメソッド (ではなく Query) を使用します。

主キーによるオブジェクトの取得

SQLite.Net は、主キーに基づいて 1 つのオブジェクトを取得する Get メソッドを提供します。

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

Linq を使用したオブジェクトの選択

Linq を使用してテーブルの内容のクエリまたは並べ替えを行うことができるように、コレクションを返すメソッドがサポート IEnumerable<T> されています。 次のコードは、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 で許可されているよりも複雑なクエリを実行する必要がある場合があります (または、パフォーマンスの向上が必要になる場合があります)。 次に示すように、Query メソッドで SQL コマンドを使用できます。

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 では、シングルスレッド、マルチスレッド、シリアル化の 3 つの異なるスレッド モードがサポートされています。 制限なしで複数のスレッドからデータベースにアクセスする場合は、 シリアル化スレッド モードを使用するように SQLite を構成できます。 このモードは、アプリケーションの早い段階 (メソッドの OnCreate 先頭など) で設定することが重要です。

スレッド モードを変更するには、 を呼び出します SqliteConnection.SetConfig。 たとえば、次のコード行は 、シリアル化 モード用に SQLite を構成します。

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

SQLite の Android バージョンには、いくつかの手順が必要な制限があります。 の SqliteConnection.SetConfig 呼び出しで のような library used incorrectlySQLite 例外が生成される場合は、次の回避策を使用する必要があります。

  1. と API をアプリで使用できるようにsqlite3_shutdownsqlite3_initialize、ネイティブ libsqlite.so ライブラリにリンクします。

    [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 と複数のスレッド」を参照してください。