Code First Migrations による自動移行

自動移行では、各変更のコード ファイルがプロジェクトになくても Code First Migrations を使用できます。 すべての変更を自動的に適用できるわけではありません。たとえば列名の変更にはコードベース移行を使用する必要があります。

Note

この記事は、読者が基本的なシナリオでの Code First Migrations の使用方法を理解していると想定しています。 それ以外の方は、先に「Code First Migrations」をお読みください。

チーム環境における推奨事項

自動移行とコードベース移行を行き来することはできますが、これはチーム開発のシナリオでは推奨されません。 ソース管理を使用する開発者チームに所属している方は、純粋な自動移行または純粋なコードベース移行のどちらかをご利用ください。 自動移行の制限から、チーム環境ではコードベース移行のご利用をお勧めします。

初期モデルとデータベースをビルドする

移行の使用を開始する前に、使用するプロジェクトと Code First モデルが必要です。 このチュートリアルでは、正規の BlogPost モデルを使用します。

  • 新しい MigrationsAutomaticDemo コンソール アプリケーションを作成する
  • プロジェクトに最新バージョンの EntityFramework NuGet パッケージを追加する
    • ツール -> ライブラリ パッケージ マネージャー -> パッケージ マネージャー コンソール
    • Install-Package EntityFramework コマンドを実行する
  • 以下に示すコードで Model.cs ファイルを追加する。 このコードでは、ドメイン モデルを構成する 1 つの Blog クラスと EF Code First コンテキストである BlogContext クラスを定義します
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity.Infrastructure;

    namespace MigrationsAutomaticDemo
    {
        public class BlogContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
        }

        public class Blog
        {
            public int BlogId { get; set; }
            public string Name { get; set; }
        }
    }
  • これでモデルが用意できました。モデルを使ってデータ アクセスを実行してみましょう。 Program.cs ファイルを以下のコードで更新します。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace MigrationsAutomaticDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db = new BlogContext())
                {
                    db.Blogs.Add(new Blog { Name = "Another Blog " });
                    db.SaveChanges();

                    foreach (var blog in db.Blogs)
                    {
                        Console.WriteLine(blog.Name);
                    }
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }
  • アプリケーションを実行すると、MigrationsAutomaticCodeDemo.BlogContext データベースが作成されたことが表示されます。

    Database LocalDB

移行を有効にする

モデルにさらに変更を加えます。

  • Blog クラスに Url プロパティを追加します。
    public string Url { get; set; }

もう一度アプリケーションを実行すると、次を示す InvalidOperationException を取得します: データベースの作成後、'BlogContext' コンテキストの背後にあるモデルが変更されました。Code First Migrations を使用したデータベースの更新を検討してください (http://go.microsoft.com/fwlink/?LinkId=238269)。

例外で示されているように、Code First Migrations の使用を開始します。 ここでは自動移行を使用したいので、?EnableAutomaticMigrations スイッチを指定します。

  • パッケージ マネージャー コンソールから Enable-Migrations –EnableAutomaticMigrations コマンドを実行します このコマンドによって、プロジェクトには Migrations フォルダーが追加されます。 この新しいフォルダーには、次のファイルが 1 つ格納されています。

  • 構成クラス。 このクラスでは、Migrations がコンテキストに対してどのように動作するかを構成できます。 このチュートリアルでは、既定の構成を使用します。 プロジェクト内の Code First コンテキストは 1 つのみのため、Enable-Migrations ではこの構成が適用されるコンテキストの種類を自動的に入力します。

 

初めての自動移行

Code First Migrations には、よく使うことになる 2 つのプライマリ コマンドがあります。

  • Add-Migration では、最後の移行が作成されてからモデルに加えた変更に基づいて、次の移行をスキャフォールディングします
  • Update-Database では、保留中の移行をデータベースに適用します

Add-Migration の使用は (どうしても必要である場合を除き) 避け、Code First Migrations で自動的に変更を計算して適用したいと思います。 Update-Database を使用して、モデルに対する変更 (新しい Blog.Url プロパティ) を Code First Migrations でデータベースにプッシュしましょう。

  • パッケージ マネージャー コンソールで Update-Database コマンドを実行します。

これで、MigrationsAutomaticDemo.BlogContext データベースが、Blogs テーブル内の Url 列を含めるように更新されました。

 

2 回目の自動移行

さらに別の変更を加えて、その変更を Code First Migrations で自動的にデータベースにプッシュしましょう。

  • 新しい Post クラスも追加します
    public class Post
    {
        public int PostId { get; set; }
        [MaxLength(200)]
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
  • BlogPost の間のリレーションシップのもう一方を形成するために、Blog クラスに Posts コレクションも追加します
    public virtual List<Post> Posts { get; set; }

次に、Update-Database を使用してデータベースを最新の状態にします。 今回は、Code First Migrations が実行している SQL を確認できるように、–Verbose フラグを指定します。

  • パッケージ マネージャー コンソールで Update-Database –Verbose コマンドを実行します。

コード ベースの移行を追加する

今度は、コードベース移行を使用した方がよい場面について見てみましょう。

  • Blog クラスに Rating プロパティを追加します。
    public int Rating { get; set; }

Update-Database を実行して、これらの変更をデータベースにプッシュします。 ただし、ここで追加しているのは null 非許容の Blogs.Rating 列です。テーブルに既存のデータがある場合は、新しい列のデータ型の CLR における既定値が割り当てられます (Rating は整数なので、0 になります)。 ただし、Blogs テーブルの既存の行が適切な評価で開始されるように、既定値の 3 を指定する必要があります。 この変更を編集できるよう、Add-Migration コマンドを使用して、コードベース移行に書き出してみましょう。 Add-Migration コマンドを使用すると、これらの移行に名前を付けることができます。ここでは、AddBlogRating という名前を付けます。

  • パッケージ マネージャー コンソールで Add-Migration AddBlogRating コマンドを実行します。
  • Migrations フォルダーに、新しい AddBlogRating 移行ができました。 移行のファイル名の先頭には、並べ替えに役立つタイムスタンプが付きます。 生成されたコードを編集して、Blog.Rating に既定値として 3 を指定します (以下のコードの 10 行目)。

この移行には、あるメタデータをキャプチャする分離コード ファイルも含まれています。 Code First Migrations は、このメタデータがあることで、先ほどコードベース移行の前に行った自動移行をレプリケートすることができます。 この点は、この移行を他の開発者が実行する場合や、実際にアプリケーションをデプロイする段階で重要になります。

    namespace MigrationsAutomaticDemo.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;

        public partial class AddBlogRating : DbMigration
        {
            public override void Up()
            {
                AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
            }

            public override void Down()
            {
                DropColumn("Blogs", "Rating");
            }
        }
    }

編集した移行は問題なさそうなので、Update-Database を使用してデータベースを最新の状態にします。

  • パッケージ マネージャー コンソールで Update-Database コマンドを実行します。

自動移行に戻る

もっと単純な変更であれば、自動移行に切り替えることができます。 各コードベース移行の分離コード ファイルに格納されているメタデータに基づいて、Code First Migrations が自動移行とコードベース移行を正しい順序で実行してくれます。

  • モデルに Post.Abstract プロパティを追加してみましょう。
    public string Abstract { get; set; }

後は Update-Database を使用し、自動移行を使用して Code First Migrations に、この変更をデータベースにプッシュさせます。

  • パッケージ マネージャー コンソールで Update-Database コマンドを実行します。

まとめ

このチュートリアルでは、自動移行を使用してモデルの変更をデータベースにプッシュする方法を見てきました。 また、より細かな制御が必要な状況を想定し、自動移行の合間に、コードベース移行をスキャフォールディングして実行する方法についても説明しました。