UWP でローカルデータベースを使いたかったので、 Entity Framework Core 1.0(旧 Entity Framework 7)で SQLite をコードファーストで試してみました。
Entity Framework Core 1.0 をインストールする
Visual Studio で作成した UWP のプロジェクトに、NuGet パッケージをインストールします。EF Core 1.0 は、まだバージョンが RC1 です。
- Install-Package EntityFramework.SQLite -Pre
インストールされたライブラリを見ると、EF 6 までは、System.Data.SQLite の SQLite.Interop.dll でしたが、EF Core 1.0 では SQLite の公式HP からダウンロードできる sqlite3.dll が配置されています。
データベースを作成する
コードファーストで利用するので、Person エンティティのクラスを定義します。
public class Person { public int ID { get; set; } public string Name { get; set; } }
DbContext クラスを継承した SampleDbContext クラスを定義します。今回は、sample.db という名前のデータベースを作成します。
public class SampleDbContext : DbContext { public DbSet<Person> Person { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var connectionString = new SqliteConnectionStringBuilder { DataSource = "sample.db" }.ToString(); optionsBuilder.UseSqlite(new SqliteConnection(connectionString)); } }
SampleDbContext クラスの EnsureCreatedAsync() メソッドを実行すると、データベースが作成されます。EF 6 までのように、構成ファイルでいろいろと設定する必要はなく、だいぶシンプルになりました。
private async void Page_Loaded(object sender, RoutedEventArgs e) { // データベースの作成 using (var db = new SampleDbContext()) { await db.Database.EnsureCreatedAsync(); } }
CRUD処理を実装する
Person テーブルの CRUD 処理を実装します。とくに説明が必要ないぐらいシンプルなコードです。
private async void InsertButton_Click(object sender, RoutedEventArgs e) { // レコードの追加 using (var db = new SampleDbContext()) { var person = new Person { Name = "Test01" }; db.Person.Add(person); await db.SaveChangesAsync(); } } private async void RetrieveButton_Click(object sender, RoutedEventArgs e) { // レコードの取得 using (var db = new SampleDbContext()) { foreach (var person in db.Person) { await new MessageDialog($"ID = {person.ID}, Name = {person.Name}").ShowAsync(); } } } private async void UpdateButton_Click(object sender, RoutedEventArgs e) { // レコードの更新 using (var db = new SampleDbContext()) { var person = db.Person.Where(x => x.ID == 1).FirstOrDefault(); person.Name = "Test02"; await db.SaveChangesAsync(); } } private async void DeleteButton_Click(object sender, RoutedEventArgs e) { // レコードの削除 using (var db = new SampleDbContext()) { var person = db.Person.Where(x => x.ID == 1).FirstOrDefault(); db.Person.Remove(person); await db.SaveChangesAsync(); } }
テーブルレイアウトのカスタマイズ
コードファーストなので、Person クラスをもとに EF の規則にしたがってテーブルが自動作成されます。例えば、ID という名前のプロパティがあれば、Primary Key や AutoIncrement が自動で設定されます。自動作成されるルールをカスタマイズすることも可能です。追加の設定を行うには2つの方法が提供されています。
- Data Annotations
- Fluent API
例えば、Name プロパティを入力必須にするには、以下のように Required を設定します。
public class Person { public int ID { get; set; } [Required] public string Name { get; set; } }
public class SampleDbContext : DbContext { (省略) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>().Property(x => x.Name).IsRequired(); base.OnModelCreating(modelBuilder); } }
どちらの方法で設定しても、テーブルの Name 列には Not Null が設定されます。
エンティティクラスにごちゃごちゃと属性を付けたくない場合には、Fluent API を使うといいと思います。こちらのサイトに記載されていますが、その他にもテーブル間のリレーションやインデックスなども細かく設定できます。
まとめ
モバイル系のアプリケーションで SQLite を使うなら、System.Data.Sqlite のライブラリに比べて、かなり楽にデータベースを操作できる ORM なので、これからは EF Core 1.0 を使っていきたいです。ASP.NET Core 1.0 と同じタイミングのはずなので、2016 年中に正式リリースが予定されています。