Xamarin.FormsでSQLiteを使う

Xamarin.FormsでSQLiteを使用するには、

専用のパッケージはもちろん必要になるのですが、

Xamarin.Formsは各プラットーフォームに指示を送る司令塔の様な役割のため、

Xamarin.Forms自体がデータベースの実ファイルを持つわけではありません。

 

なので、Xamarin.FormsでSQLiteを使用するには、

各プラットフォームからデータベースへのパスを渡してあげる必要があります。

 ※ここではSqliteSampleというソリューションを作成しました。

 

Android

MainActivity.cs


using Android.App;
using Android.Content.PM;
using Android.OS;

namespace SqliteSample.Droid
{
	[Activity(Label = "SqliteSample.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
	public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
	{
		protected override void OnCreate(Bundle bundle)
		{
			TabLayoutResource = Resource.Layout.Tabbar;
			ToolbarResource = Resource.Layout.Toolbar;

			base.OnCreate(bundle);

			global::Xamarin.Forms.Forms.Init(this, bundle);

			//指定したファイルのパスを取得します。
			var dbPath = GetLocalFilePath("sqlitetest.db3");

			//この段階ではまだエラーになります。
			LoadApplication(new App(dbPath));
		}

		public static string GetLocalFilePath(string filename)
		{
			//指定されたファイルのパスを取得します。なければ作成してそのパスを返却します
			var path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
			return System.IO.Path.Combine(path, filename);
		}
	}
} 
    

iOS

AppDelegate.cs


using System;

using Foundation;
using UIKit;

namespace SqliteSample.iOS
{
	[Register("AppDelegate")]
	public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
	{
		public override bool FinishedLaunching(UIApplication app, NSDictionary options)
		{
			global::Xamarin.Forms.Forms.Init();

			//指定したファイルのパスを取得します。
			var dbPath = GetLocalFilePath("culculate.db3");

			//この段階ではまだエラーになります。
			LoadApplication(new App(dbPath));

			return base.FinishedLaunching(app, options);
		}

		public static string GetLocalFilePath(string filename)
		{
			//指定されたファイルのパスを取得します。なければ作成してそのパスを返却します
			var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			var libFolder = System.IO.Path.Combine(docFolder, "..", "Library", "Databases");

			if (!System.IO.Directory.Exists(libFolder)) {
				System.IO.Directory.CreateDirectory(libFolder);
			}

			return System.IO.Path.Combine(libFolder, filename);
		}
	}
}
    

Xamarin.Forms

App.xaml.cs


using Xamarin.Forms;

namespace SqliteSample
{
	public partial class App : Application
	{
		//データベースのパスを格納
		public static string dbPath;

		//コンストラクタの引数にstring型の引数を追加
		public App(string dbPath)
		{
			//AppのdbPathに引数のパスを設定します
			App.dbPath = dbPath;

			InitializeComponent();

			MainPage = new SqliteSamplePage();
		}

		protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}
    

※ここではAppクラスのコンストラクタの引数を変更して、データベースのパスを渡していますが、

DependencyServiceクラスを使用する方法でも問題ありません(むしろそちらの方が良いと思います)。

 

 

次にXamarin.Forms及び各プラットーフォームのプロジェクトへ

SQLite-net PCLパッケージを追加します。

現在(2017年3月5日時点)、SQLite-net PCLの最新バージョンは、

1.3.1ですが、このバージョンを追加しようとするとエラーになるため、

1.2.1を選択してください。

または、Xamarin.Formsのプロジェクトオプションを開き、

ビルド > 全般 の.Net Portable をPCL 4.5 - Profile259 に変更します。

 

f:id:dev_suesan:20170305205427p:plain

 

f:id:dev_suesan:20170306001249p:plain

 

さらに、iOSプロジェクトで使用する場合は、

iOSのプロジェクトオプションを開き、

ビルド > iOS Build のリンカーの動作をフレームワーク SDK のみをリンクするを

選択します。

 

これでSQLiteを使うための準備が整いました。

実際の使用方法の例です。

まず、今回の例ではidと名前だけを格納するテーブルUserを作ります。

UserModelというクラスを作成し、そのクラスにテーブル構造を定義し、

さらにインサート・セレクトを行うメソッドを用意します。

UserModel.cs


using System;
using System.Collections.Generic;
using SQLite;

namespace SqliteSample
{
	//テーブル名を指定
	[Table("User")]
	public class UserModel
	{
		//プライマリキー 自動採番されます
		[PrimaryKey, AutoIncrement, Column("_id")]
		//idカラム
		public int Id { get; set; }
		//名前カラム
		public string Name { get; set; }

		//Userテーブルに行追加するためのメソッドです
		public static void insertUser(string name)
		{
			//データベースに接続します
			using (SQLiteConnection db = new SQLiteConnection(App.dbPath)) {

				try {
					//データベースにUserテールブを作成します
					db.CreateTable();

					//Userテーブルに行追加します
					db.Insert(new UserModel() { Name = name });

					db.Commit();

				} catch (Exception e) {
					
					db.Rollback();
					System.Diagnostics.Debug.WriteLine(e);

				}
			}
		}

		//Userテーブルの行データを取得します
		public static List selectUser()
		{
			using (SQLiteConnection db = new SQLiteConnection(App.dbPath)) {

				try {
					//データベースに指定したSQLを発行します
					return db.Query("SELECT * FROM [User] ");

				} catch (Exception e) {

					System.Diagnostics.Debug.WriteLine(e);
					return null;
				}
			}
		}
	}
}
    

 

SqliteSamplePage.xaml.cs
using Xamarin.Forms;

namespace SqliteSample
{
	public partial class SqliteSamplePage : ContentPage
	{
		public SqliteSamplePage()
		{
			InitializeComponent();

			var layout = new StackLayout { HorizontalOptions = LayoutOptions.Center, Margin = new Thickness { Top = 100 } };

			//Userテーブルに適当なデータを追加
			UserModel.insertUser("鈴木");
			UserModel.insertUser("田中");
			UserModel.insertUser("斎藤");

			//Userテーブルの行データを取得
			var query = UserModel.selectUser();

			foreach (var user in query) {

				//Userテーブルの名前列をLabelに書き出します
				layout.Children.Add(new Label { Text = user.Name });
			}

			Content = layout;
		}
	}
}

 

これで実行すると下の画像のようにテーブルに格納したデータが表示されます

 

 

f:id:dev_suesan:20170306003202p:plain