rksoftware

Visual Studio とか C# とかが好きです

Xamarin Forms で SQLite を使う

Xamarin.Forms で SQLite を使うには SQLite-net を使うのが簡単そうです。
[ SQLite-net https://github.com/praeclarum/sqlite-net ]

■ NuGet パッケージのインストール

・Forms プロジェクトを .NET Standard で作成します。
・NuGet から「sqlite-net-pcl」を共通プロジェクトとプラットフォーム毎のプロジェクト全てにインストールします。
※Android、と iOS のみで確認しています。

!!注意!!
sqlite-net-pcl」で検索すると似た名前のパッケージがいくつか見つかります。注意して選択してください。
私の環境では一番目に「SQLite.Net-PCL-Silverlight」というパッケージが表示されるなどしました。
Silverlight... 2018 年にこの名前を目にするとは...

■ コード

まずは動かしてみたコードを

public class Tran
{
    [SQLite.PrimaryKey, SQLite.AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime TimeStamp { get; set; }
    public decimal Value { get; set; }
}

public partial class MainPage : ContentPage
{
    public static string DbPath { get; } = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "SQLiteDataBase.db");
    public MainPage()
    {
        InitializeComponent();
        var sl = (StackLayout)(this.Content = new StackLayout());
        var button1 = new Button() { Text = "Create Table" };
        var button2 = new Button() { Text = "Insert" };
        var button3 = new Button() { Text = "Select" };
        var button4 = new Button() { Text = "Query" };
        sl.Children.Add(button1);
        sl.Children.Add(button2);
        sl.Children.Add(button3);
        sl.Children.Add(button4);
        button1.Clicked += Button1_Clicked;
        button2.Clicked += Button2_Clicked;
        button3.Clicked += Button3_Clicked;
        button4.Clicked += Button4_Clicked;
    }

    // Query
    private void Button4_Clicked(object sender, EventArgs e)
    {   // データ取得
        using (var db = new SQLite.SQLiteConnection(DbPath))
        {   // Select
            foreach (var row in db.Query<Tran>("Select * From Tran Where Name like ? ", $"%3%"))
                Console.WriteLine($"Tran: {row.Id}, {row.Name}, {row.TimeStamp}, {row.Value}");
        }
    }

    // Select
    private void Button3_Clicked(object sender, EventArgs e)
    {   // データ取得
        using (var db = new SQLite.SQLiteConnection(DbPath))
        {   // Select
            foreach (var row in db.Table<Tran>().Where(r => r.Name.Contains("3")))
                Console.WriteLine($"Tran: {row.Id}, {row.Name}, {row.TimeStamp}, {row.Value}");
        }
    }

    // Insert
    private void Button2_Clicked(object sender, EventArgs e)
    {   // データ追加
        using (var db = new SQLite.SQLiteConnection(DbPath))
        {   // Insert
            db.Insert(new Tran() { Name = "Tran 12 Name", TimeStamp = DateTime.Now, Value = 1.1m });
            db.Insert(new Tran() { Name = "Tran 23 Name", TimeStamp = DateTime.Now, Value = 2.2m });
            db.Insert(new Tran() { Name = "Tran 34 Name", TimeStamp = DateTime.Now, Value = 3.3m });
            db.Insert(new Tran() { Name = "Tran 45 Name", TimeStamp = DateTime.Now, Value = 4.4m });
        }
    }

    // Create Table
    private void Button1_Clicked(object sender, EventArgs e)
    {   // データベース初期設定
        using (var db = new SQLite.SQLiteConnection(DbPath))
        {   // Create Table
            db.CreateTable<Tran>();
        }
    }
}

■ データベースの生成

データベースファイルを作成する処理はすべて吸収してくれています。
我々は、データベースファイルのパスを指定するだけでうまいことやってくれるようです。

■ テーブルの生成

まず Entity のクラスを作って

public class Tran
{
    [SQLite.PrimaryKey, SQLite.AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime TimeStamp { get; set; }
    public decimal Value { get; set; }
}

CreateTable メソッドを使えば良いだけです。

using (var db = new SQLite.SQLiteConnection(DbPath))
{   // Create Table
    db.CreateTable<Tran>();
}

とても簡単。

■ Insert

データの Insert も簡単。
Insert メソッドにデータオブジェクトのインスタンスを渡すだけ。

using (var db = new SQLite.SQLiteConnection(DbPath))
{   // Insert
    db.Insert(new Tran() { Name = "Tran 12 Name", TimeStamp = DateTime.Now, Value = 1.1m });
    db.Insert(new Tran() { Name = "Tran 23 Name", TimeStamp = DateTime.Now, Value = 2.2m });
    db.Insert(new Tran() { Name = "Tran 34 Name", TimeStamp = DateTime.Now, Value = 3.3m });
    db.Insert(new Tran() { Name = "Tran 45 Name", TimeStamp = DateTime.Now, Value = 4.4m });
}

■ Select パターン1

Select は大きく 2 通りの方法があります。
まず一つ目は、EntityFramework のように Where メソッドで対象を絞る条件を与えられるパターンです。

using (var db = new SQLite.SQLiteConnection(DbPath))
{   // Select
    foreach (var row in db.Table<Tran>().Where(r => r.Name.Contains("3")))
        Console.WriteLine($"Tran: {row.Id}, {row.Name}, {row.TimeStamp}, {row.Value}");
}

■ Select パターン2

直接クエリ文を渡せるパターンです。
複雑なデータを扱う場合や、RDB の得意な方と組み時にも安心ですね。

using (var db = new SQLite.SQLiteConnection(DbPath))
{   // Select
    foreach (var row in db.Query<Tran>("Select * From Tran Where Name like ? ", $"%3%"))
        Console.WriteLine($"Tran: {row.Id}, {row.Name}, {row.TimeStamp}, {row.Value}");
}

■ その他のメソッド

今回は試していませんが、Delete、Update、OrderBy、Join など必要な機能はそろっていそうです。

■ 非同期

今回は SQLiteConnection クラスを試しましたが、各種処理が非同期で行える SQLiteAsyncConnection クラスもあります。
アプリの起動時の処理やデータ更新などで時間がかかる場合に頼りになりそうです。