コンウェイとピーターの狭間で

ずっと放置しつつQiitaに移ったりしていましたが、スマートホームについて書いていこうかと

Entity Framework Core (Entity Framework 7)を試してみる

いつの間にやらEntity Framework Coreがリリースされてたのですね。 Entity Framework Core を試しつつ、Entity Framework 6.xとの違いを見ていこうと思います。

Sqliteが公式になってる

公式サイトのDatabase ProviderにSqliteの文字が!

EntityFramework/README.md at dev · aspnet/EntityFramework · GitHub

EntityFrameworkの中の人が作ってるのかな? SQLServerはLocalDBがあるとは言え、割と重いですし、 ファイルを消すだけでさくっとDBを消せるSqliteは魅力です。 単体テストも書きやすいですしね。 単体テストに関してはInMemoryが追加されたので、気になるところ。

SqliteでMigrationに対応してる!

今まではCode Firstでテーブルを作ることはできましたが、 モデルの変更を検知して既存のテーブルに差分を適用する、 なんてことはできませんでした。

これができるのがSQLServerだけだったイメージです。 それが、公式になっているせいかSQLiteも対応していました。

もしかすると共有の機能が強化され、他のDBでもできるかもしれません。

SqliteでDateTimeOffsetに対応してる

日付を扱ううえでDateTimeOffsetを使うことがあります。 Entity Framework 6.xではSqliteの場合はDateTimeOffset型は非対応でした。 Entity Framework Coreでは、一応使えました。 ただし、Offset(タイムゾーンを表す)は0にすること、が要件のようなので 実質DateTimeとかわりません。 しかし、SQLServerSqliteで同じデータモデルが使えるのが良いかもしれません。 もう少し調べたいところですが。

Select句が柔軟になってる!

Entity Framework 6.xではSelectメソッド、WhereメソッドはSQLに変換されるため、 C#ラムダ式とはいえ割と制限がありました。 例えば、こんな呼び方はエラーになります。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new TempContext())
        {
            var people = context.People.Select(_ => new PersonDomainModel(_.Id, _.Name)); //<-複雑なSelectメソッド
        }
    }
}
public class TempContext : DbContext
{
    public DbSet<Person> People { get; set; }
    //(略)
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class PersonDomainModel
{
    public PersonDomainModel(int id, string name)
    {
        Id = id;
        Name = name;
    }
    public int Id { get; }
    public string Name { get; }
}

この制限がわかりにくくて、ランタイムエラーになるのが気になっていました。

それが、Entity Framework Coreではさらっと通ります。 しかもログを出してみると、ちゃんと必要なColumnだけクエリされてるっぽい。

SELECT TOP(1) [].[Id], [].[Name] FROM [People] AS [_]

Selectメソッドの式木を解析して、使われているColumnだけSQLに変換しているのでしょう。 ただし、Whereメソッドは全レコードをC#側で実行されるようなので Whereメソッドは注意が必要です。

この機能は、Client Evaluation というのかな?

Client vs. Server Evaluation — Entity Framework Core 1.0.0 documentation

設定でOffにできるようですが、WhereメソッドだけOffにできたらいいんだけどできるのかな?

Database.SetInitializerが無い

SQLServerの場合、こんな感じ書くと起動時にデータベースをクリアしてくれました。

Database.SetInitializer(new DropCreateDatabaseAlways<EntitiesContext>());

また、データモデルからテーブルを自動Migrationなんてこともできたはず。 この機能は無くなっていました。

Visual Studioのパッケージマネージャコンソールでコマンドを打ち込むことでデータベースは更新するようです。

Add-Migration
Update-Database

ただ、この機能を使うにはNugetで Microsoft.EntityFrameworkCore.Tools を追加する必要がありますが、 2016/7/23現在、Pre-Releaseのようです。

.NET Core CLI

.NET Core CLI というキーワードがちょいちょい出てきます。

.NET - Powerful Open Source Development

この.NET Core CLIでもデータベースの更新ができるようです。 まだ使ったことはないのですが、上のMigrationを使うのにVisual Studioが必要なので Visual Studio無しでデータベースを更新する仕組みなんですかね?