Entity-framework-code-first-migration
Entity Framework-Code First Migration
Entity Framework 4.3には新しいCode First Migrations機能が含まれており、モデルの経時変化に応じてデータベーススキーマを段階的に進化させることができます。 ほとんどの開発者にとって、これは4.1および4.2リリースのデータベース初期化オプションに対する大きな改善であり、モデルの変更時にデータベースを手動で更新するか、削除して再作成する必要がありました。
- Entity Framework 4.3より前、既にデータ(シードデータ以外)または既存のストアドプロシージャ、トリガーなどがある場合 データベースでは、これらの戦略はデータベース全体を削除して再作成するために使用されるため、データやその他のDBオブジェクトが失われます。
- 移行により、既存のデータや他のデータベースオブジェクトを失うことなくモデルが変更されると、データベーススキーマが自動的に更新されます。
- MigrateDatabaseToLatestVersionと呼ばれる新しいデータベース初期化子を使用します。
移行には2種類あります-
- 自動移行
- コードベースの移行
自動移行
自動移行は、Entity Framework 4.3で初めて導入されました。 自動移行では、コードファイルでデータベースの移行を手動で処理する必要はありません。 たとえば、変更ごとに、ドメインクラスも変更する必要があります。 ただし、自動移行では、パッケージマネージャーコンソールでコマンドを実行するだけでこれを実行できます。
自動移行の次の段階的なプロセスを見てみましょう。
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") {}
public virtual DbSet<Course> Courses { get; set; }
public virtual DbSet<Enrollment> Enrollments { get; set; }
public virtual DbSet<Student> Students { get; set; }
}
アプリケーションを実行する前に、自動移行を有効にする必要があります。
- ステップ1 *-ツール→NuGetパッケージマネージャー→パッケージマネージャーコンソールからパッケージマネージャーコンソールを開きます。
- ステップ2 *-自動移行を有効にするには、パッケージマネージャーコンソールで次のコマンドを実行します。
PM> enable-migrations -EnableAutomaticMigrations:$true
- ステップ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" }
// );
}
}
}
- ステップ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; }
}
- ステップ5 *-自動移行を設定しました。 アプリケーションを実行すると、モデルを変更すると、自動的に移行が処理されます。
- ステップ6 *-ご覧のとおり、1つのシステムテーブルMigrationHistoryも他のテーブルと共にデータベースに作成されます。MigrationHistoryでは、自動移行によりデータベース変更の履歴が維持されます。
- ステップ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; }
}
- ステップ8 *-次のコードに示すように、コンテキストクラスに上記のクラスのDBSetを追加することを忘れないでください。
public virtual DbSet<StudentLogIn> StudentsLogIn { get; set; }
- ステップ9 *-アプリケーションを再度実行すると、StudentsLogInテーブルがデータベースに追加されます。
上記の自動移行の手順は、エンティティに対してのみ機能します。 たとえば、別のエンティティクラスを追加したり、既存のエンティティクラスを削除したりすると、正常に移行されます。 ただし、エンティティクラスにプロパティを追加または削除すると、例外がスローされます。
- ステップ10 *-プロパティの移行を処理するには、構成クラスコンストラクターでAutomaticMigrationDataLossAllowed = trueを設定する必要があります。
public Configuration() {
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
ContextKey = "EFCodeFirstDemo.MyContext";
}
コードベースの移行
新しいアプリケーションを開発すると、データモデルは頻繁に変更され、モデルが変更されるたびにデータベースとの同期が失われます。 データモデルを変更するたびにデータベースを自動的に削除して再作成するようにEntity Frameworkを構成しました。 コードベースの移行は、移行をさらに制御したい場合に便利です。
- エンティティクラスを追加、削除、または変更するか、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; }
}
- ステップ1 *-アプリケーションを実行する前に、移行を有効にする必要があります。
- ステップ2 *-ツール→NuGetパッケージマネージャー→パッケージマネージャーコンソールからパッケージマネージャーコンソールを開きます。
- ステップ3 *-移行はすでに有効になっています。次のコマンドを実行して、アプリケーションに移行を追加します。
PM> add-migration "UniDB Schema"
- ステップ4 *-コマンドが正常に実行されると、次の画像に示すように、タイムスタンププレフィックスを付けてコマンドに渡したパラメーターの名前で、Migrationフォルダーに新しいファイルが作成されます。
- ステップ5 *-「update-database」コマンドを使用して、データベースを作成または更新できます。
PM> Update-Database -Verbose
「-Verbose」フラグは、コンソールでターゲットデータベースに適用されているSQLステートメントを表示することを指定します。
- ステップ6 *-学生クラスにもう1つのプロパティ「年齢」を追加し、更新ステートメントを実行します。
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が追加されていることがわかります。
理解を深めるために、上記の例を段階的に実行することをお勧めします。