なか日記

一度きりの人生、楽しく生きよう。

EntityFrameworkでの自動マイグレーションを再度試してみた

以前、EntityFrameworkでの自動マイグレーションを試してみましたが、なんだかうまくいきませんでした。

そんな中、「.NET開発テクノロジ入門 2014年版 VisualStudio2013対応版 (MSDNプログラミングシリーズ)」を読んでちょっと勉強したので手を動かしてみることにします。 日本語が不自由そうなのは大目に見て下さい。

初期サンプルソース

まずはこんなソースを用意しました。この状態ではまだEnable-Migrationを実行していません。

    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory);

            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<AppDbContext>());

            var db = new AppDbContext();
            db.Articles.Add(new Article() { Title = "test" });
            db.SaveChanges();
        }
    }

    public class AppDbContext : DbContext
    {
        public DbSet<Article> Articles { get; set; }
    }

    public class Article
    {
        public int Id { get; set; }

        public string Title { get; set; }
    }

データベースの初期化は一旦、DropCreateDatabaseIfModelChangesを指定しますが、一度実行してデータベースが作成されたのを確認したら

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<AppDbContext>());

の行自体を削除しておきます。

モデルを変更

モデルにプロパティ(Content)を追加します。

    public class Article
    {
        public int Id { get; set; }

        public string Title { get; set; }
        public string Content { get; set; }
    }

これでプログラムを実行するとモデルが変更になっているので以下の様な例外が発生します。

The model backing the 'AppDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

そこで、マイグレーションを有効にしましょう。

自動マイグレーションの設定

パッケージマネージャコンソールから以下のコマンドを実行して、自動マイグレーションを有効にします。

PM> Enable-Migrations -EnableAutomaticMigrations

-EnableAutomaticMigrationsを付けたときと付けなかったときの違いは、ConfigurationクラスのAutomaticMigrationsEnabled プロパティがtrueになるか、falseになるかの違いのようです。

public Configuration()
{
    AutomaticMigrationsEnabled = true;
    ContextKey = "EFSample.AppDbContext";
}

ここを切り替えれば自動<=>手動マイグレーションの切り替えができそうです。

これで再度プログラムを実行してみるとやはり先ほどと同じ例外が発生します。

データベースの自動マイグレーションを手動で行う

パッケージマネージャコンソールから以下のコマンドを実行して、データベースをマイグレーションします。

PM>  Update-Database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending explicit migrations.
Applying automatic migration: 201407041710393_AutomaticMigration.
Running Seed method.

しかし、モデルを変更する度に「Update-Database」を実行するのは手間がかかると思います。そこで、次の様にして自動でマイグレーションされる様にします。

データベースの自動マイグレーションを自動で行う

以下のようにMigrateDatabaseToLatestVersionで初期化するとアプリケーション実行時に自動でデータベースをマイグレーションしてくれるようになります。

Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, Configuration>());

自動マイグレーションでデータが消えるといやん

自動マイグレーションは手間がかからず楽ちんですが、テーブルをDrop後にCreateしないといけないようなモデルの変更があった場合にはどうなるのでしょうか。

試しにArticleクラスのContentプロパティを削除して実行してみましょう。すると以下の様な例外が発生します。

Automatic migration was not applied because it would result in data loss. Set AutomaticMigrationDataLossAllowed to 'true' on your DbMigrationsConfiguration to allow application of automatic migrations even if they might cause data loss. Alternately, use Update-Database with the '-Force' option, or scaffold an explicit migration.

「データ喪失が発生するから自動マイグレーションはしなかったよ」という事になります。安心ですね。

必要に応じてデータのバックアップを取り、「Update-Database -Force」すれば良いと思います。

使い所

.NET開発テクノロジ入門 2014年版 VisualStudio2013対応版 (MSDNプログラミングシリーズ)」にも書いてありましたが、自動マイグレーションはモデルを頻繁に変更する開発初期の段階で使用するといいと思います。ある程度モデルが固まってきた段階(もしくはリリース後)で手動マイグレーションに切り替えるのがよろしいかと思います。

Entity Framework 6 Recipes

Entity Framework 6 Recipes