Entity Framework 4.3 Beta 1 が昨日公開されました。詳細は ADO.NET team blog を見た方が早いと思います。
EF 4.3 Beta 1 Released - ADO.NET Blog - Site Home - MSDN Blogs
要約してしまうと以下の通り。
- マイグレーション対応
- Enable-Migrations / Update-Database コマンドを追加
- 専用のイニシャライザ
- XML ドキュメントコメントが完璧に
- DbContext API のバグ修正
- GetDatabaseValues のバグ
- DbSet の名前に Unicode が使えなかったバグ
基本的には
Entity Framework 4.2 + マイグレーション対応 + バグ修正 = Entity Framework 4.3
と思っておけばいい感じがします。ちなみに Enum サポートなどは .NET 4.5 向けに出る Entity Framework 5.0 での対応になるみたいですね。
と、EF 4.3 自体の話はこれぐらいにしておいて、早速マイグレーションを試してみたいと思います。EF 4.3 には以下の二種類のマイグレーション方法が用意されています。
- Code-Based Migrations
- Automatic Migrations
結局のところ自動でやるか、手動でやるかの違いしかないみたいですが、Automatic Migrations の場合には Code-Based Migrations も部分的に適用できるみたいなので、殆どの場合は Automatic Migrations でいいんじゃないかと思います。
今回は簡単に試してみたいので Automatic Migrations を使ってみます。
EF 4.3 は NuGet ですでに配布されているので、普通に MVC 3 プロジェクトを作って更新することが出来ます。方法としてはコマンドに -IncludePrerelease スイッチを付けるだけです。
// インストール時 Install-Package EntityFramework -IncludePrerelease // アップデート時 Update-Package -IncludePrerelease
EF 4.3 を使う準備が出来たので、モデルを用意しました。
public class Product { public int ProductId { get; set; } public string Name { get; set; } }
いつものように Product クラスですが、今回はマイグレーションしたいので Name プロパティだけ用意しておきました。登録に必要なコントローラや DbContext やビューはスキャフォールディングで適当に作ってください。
この時点でアプリケーションを動かすと、以下のように自動的にテーブルが生成されます。一応、データの確認も行っておきます。
それでは Product クラスに Summary という string 型のプロパティを追加して、もう一度実行してみます。
当然ですがエラーになってしまいましたね。なのでコードファースト開発ではイニシャライザとして DropCreateDatabaseIfModelChanges などを使って、モデルが変更された場合にはテーブルを作り直すようにしていました。
// モデルが変更された場合にはテーブルを作り直す Database.SetInitializer(new DropCreateDatabaseAlways<ProductContext>())
しかし、EF 4.3 では MigrateDatabaseToLatestVersion という新しいイニシャライザが追加されました。これを使えば自動的にマイグレーションしてくれるのですが、型パラメータを見ると TMigrationsConfiguration というものが必要になっています。
この TMigrationsConfiguration に指定するクラスは Package Manager Console で簡単に生成することが出来ます。以下のコマンドを入力するだけです。
// マイグレーションを有効にするためのクラスを追加 Enable-Migrations
実行すると Migrations 名前空間が追加されて、中には Configuration という名前のクラスが生成されます。
namespace MvcApplication3.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<Models.ProductContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(MvcApplication3.Models.ProductContext context) { // This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method // to avoid creating duplicate seed data. E.g. // // context.People.AddOrUpdate( // p => p.FullName, // new Person { FullName = "Andrew Peters" }, // new Person { FullName = "Brice Lambson" }, // new Person { FullName = "Rowan Miller" } // ); // } } }
パッと見るだけで大体わかると思いますが、AutomaticMigrationsEnabled に true をセットすると Automatic Migrations が有効になります。ってそのまんまの意味です。Seed メソッドもコメントにある通り、AddOrUpdate 拡張メソッドを使って初期データを登録するために使いますが、今回は初期値の必要がないのでそのままにしておきます。
最後に Global.asax にイニシャライザを設定して完了です。
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ProductContext, Configuration>());
それでは実際に確認してみました。
Summary カラムが追加され、データ自体も保持されていることが確認できました。ちなみに今は初期値が null になっていますが Code-Based Migrations を部分的に使うことで、カラムの初期値を指定出来ます。しかし、それはまた今度扱ってみたいと思います。
今回はイニシャライザを指定してマイグレーションを実行時に自動で行うようにしましたが、Update-Database コマンドを実行すると任意のタイミングでマイグレーションを行えます。即座にテーブルに反映したい場合には非常に便利ですね。