エンティティフレームワーク-コードファーストマイグレーション

Entity Framework 4.3には、モデルが時間の経過とともに変化するにつれてデータベーススキーマを段階的に進化させることができる新しいCode FirstMigrations機能が含まれています。ほとんどの開発者にとって、これは、モデルが変更されたときにデータベースを手動で更新するか、データベースを削除して再作成する必要があった4.1および4.2リリースのデータベース初期化オプションを大幅に改善したものです。

  • Entity Framework 4.3より前は、データベースにデータ(シードデータ以外)または既存のストアドプロシージャ、トリガーなどが既にある場合、これらの戦略はデータベース全体を削除して再作成するために使用されていたため、データやその他のDBが失われていました。オブジェクト。

  • 移行により、既存のデータやその他のデータベースオブジェクトを失うことなくモデルが変更されたときに、データベーススキーマが自動的に更新されます。

  • MigrateDatabaseToLatestVersionと呼ばれる新しいデータベース初期化子を使用します。

移行には2種類あります-

  • 自動移行
  • コードベースの移行

自動移行

自動移行は、Entity Framework4.3で最初に導入されました。自動移行では、コードファイルでデータベース移行を手動で処理する必要はありません。たとえば、変更ごとに、ドメインクラスも変更する必要があります。ただし、自動移行では、パッケージマネージャーコンソールでコマンドを実行するだけでこれを実行できます。

自動移行の次のステップバイステップのプロセスを見てみましょう。

コードファーストアプローチを使用する場合、アプリケーション用のデータベースがありません。

この例では、次のコードに示すように、Student、Course、Enrollmentなどの3つの基本クラスから始めます。

public class Enrollment {
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }
	
   public virtual Course Course { get; set; }
   public virtual Student Student { get; set; }

}

public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }

}

public class Course {
   public int CourseID { get; set; }
   public string Title { get; set; }
   [Index]
   public int Credits { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }

}

以下はコンテキストクラスです。

public class MyContext : DbContext {
   public MyContext() : base("MyContextDB") {}
   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public virtual DbSet<Student> Students { get; set; }
}

アプリケーションを実行する前に、自動移行を有効にする必要があります。

Step 1 − [ツール]→[NuGetパッケージマネージャー]→[パッケージマネージャーコンソール]からパッケージマネージャーコンソールを開きます。

Step 2 −自動移行を有効にするには、パッケージマネージャーコンソールで次のコマンドを実行します。

PM> enable-migrations -EnableAutomaticMigrations:$true

Step 3 −コマンドが正常に実行されると、次のコードに示すように、プロジェクトのMigrationフォルダーに内部の封印されたConfigurationクラスが作成されます。

namespace EFCodeFirstDemo.Migrations {

   using System;
   using System.Data.Entity;
   using System.Data.Entity.Migrations;
   using System.Linq;
	
   internal sealed class Configuration : DbMigrationsConfiguration<EFCodeFirstDemo.MyContext> {

      public Configuration() {
         AutomaticMigrationsEnabled = true;
         ContextKey = "EFCodeFirstDemo.MyContext";
      }

      protected override void Seed(EFCodeFirstDemo.MyContext 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" }
         //  );
      }
   }
}

Step 4 −新しいDB初期化戦略MigrateDatabaseToLatestVersionを使用して、コンテキストクラスにデータベース初期化子を設定します。

public class MyContext : DbContext {

   public MyContext() : base("MyContextDB") {
      Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, 
         EFCodeFirstDemo.Migrations.Configuration>("MyContextDB"));
   }

   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public virtual DbSet<Student> Students { get; set; }

}

Step 5−自動移行を設定しました。アプリケーションを実行すると、モデルを変更したときに自動的に移行が処理されます。

Step 6−ご覧のとおり、1つのシステムテーブル__MigrationHistoryも、他のテーブルとともにデータベースに作成されます。__MigrationHistoryでは、自動移行によってデータベース変更の履歴が維持されます。

Step 7−ドメインクラスとして別のエンティティクラスを追加してアプリケーションを実行すると、データベースにテーブルが作成されます。次のStudentLogInクラスを追加しましょう。

public class StudentLogIn {
   [Key, ForeignKey("Student")]
   public int ID { get; set; }
   public string EmailID { get; set; }
   public string Password { get; set; }
	
   public virtual Student Student { get; set; }
}

Step 8 −次のコードに示すように、コンテキストクラスに上記のクラスのDBSetを追加することを忘れないでください。

public virtual DbSet<StudentLogIn> StudentsLogIn { get; set; }

Step 9 −アプリケーションを再度実行すると、StudentsLogInテーブルがデータベースに追加されていることがわかります。

自動移行について説明した上記の手順は、エンティティでのみ機能します。たとえば、別のエンティティクラスを追加したり、既存のエンティティクラスを削除したりすると、正常に移行されます。ただし、エンティティクラスにプロパティを追加または削除すると、例外がスローされます。

Step 10 −プロパティの移行を処理するには、構成クラスのコンストラクターでAutomaticMigrationDataLossAllowed = trueを設定する必要があります。

public Configuration() {
   AutomaticMigrationsEnabled = true;
   AutomaticMigrationDataLossAllowed = true;
   ContextKey = "EFCodeFirstDemo.MyContext";
}

コードベースの移行

新しいアプリケーションを開発すると、データモデルが頻繁に変更され、モデルが変更されるたびに、データベースと同期しなくなります。データモデルを変更するたびにデータベースを自動的に削除して再作成するようにEntityFrameworkを構成しました。コードベースの移行は、移行をより細かく制御したい場合に役立ちます。

  • エンティティクラスを追加、削除、変更するか、DbContextクラスを変更すると、次にアプリケーションを実行すると、既存のデータベースが自動的に削除され、モデルに一致する新しいデータベースが作成され、テストデータがシードされます。

  • Code First Migrations機能は、データベースを削除して再作成する代わりに、Code Firstがデータベーススキーマを更新できるようにすることで、この問題を解決します。アプリケーションをデプロイするには、移行を有効にする必要があります。

データベース内の変更を移行するための基本的なルールは次のとおりです-

  • 移行を有効にする
  • 移行を追加
  • データベースを更新する

次のコードベース移行のステップバイステップのプロセスを見てみましょう。

コードファーストアプローチを使用する場合、アプリケーション用のデータベースがありません。

この例では、次のコードに示すように、Student、Course、Enrollmentなどの3つの基本クラスから再開します。

public class Enrollment {
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }
	
   public virtual Course Course { get; set; }
   public virtual Student Student { get; set; }

}

public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }

}

public class Course {
   public int CourseID { get; set; }
   public string Title { get; set; }
   [Index]
   public int Credits { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }

}

以下はコンテキストクラスです。

public class MyContext : DbContext {

   public MyContext() : base("MyContextDB") {
      Database.SetInitializer(new MigrateDatabaseToLatestVersion<
         MyContext, EFCodeFirstDemo.Migrations.Configuration>("MyContextDB"));
   }

   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public virtual DbSet<Student> Students { get; set; }

}

Step 1 −アプリケーションを実行する前に、移行を有効にする必要があります。

Step 2 − [ツール]→[NuGetパッケージマネージャー]→[パッケージマネージャーコンソール]からパッケージマネージャーコンソールを開きます。

Step 3 −移行はすでに有効になっています。次のコマンドを実行して、アプリケーションに移行を追加します。

PM> add-migration "UniDB Schema"

Step 4 −コマンドが正常に実行されると、次の図に示すように、コマンドに渡したパラメーターの名前とタイムスタンププレフィックスが付いた新しいファイルがMigrationフォルダーに作成されたことがわかります。

Step 5 −「update-database」コマンドを使用してデータベースを作成または更新できます。

PM> Update-Database -Verbose

「-Verbose」フラグは、コンソールでターゲットデータベースに適用されているSQLステートメントを表示することを指定します。

Step 6 −学生クラスにもう1つのプロパティ「Age」を追加してから、updateステートメントを実行してみましょう。

public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public int Age { get; set; }
   public DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }

}

PM→Update-Database–Verboseを実行すると、コマンドが正常に実行されると、新しい列Ageがデータベースに追加されていることがわかります。

理解を深めるために、上記の例を段階的に実行することをお勧めします。