實體框架 - 程式碼優先遷移



實體框架 4.3 包含一個新的程式碼優先遷移功能,允許您隨著模型隨時間變化而逐步發展資料庫模式。對於大多數開發者來說,這比 4.1 和 4.2 版本中需要您手動更新資料庫或在模型更改時刪除並重新建立資料庫的資料庫初始化程式選項有了很大的改進。

  • 在實體框架 4.3 之前,如果您已經在資料庫中擁有資料(種子資料除外)或現有的儲存過程、觸發器等,這些策略都會刪除整個資料庫並重新建立它,因此您會丟失資料和其他資料庫物件。

  • 透過遷移,當您的模型發生更改時,它將自動更新資料庫模式,而不會丟失任何現有資料或其他資料庫物件。

  • 它使用一個名為 MigrateDatabaseToLatestVersion 的新的資料庫初始化程式。

遷移有兩種型別:

  • 自動遷移
  • 基於程式碼的遷移

自動遷移

自動遷移首先在實體框架 4.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
Command

步驟 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 - 使用新的資料庫初始化策略 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 - 您已設定自動遷移。當您執行應用程式時,當您更改模型時,它會自動處理遷移。

Migration

步驟 6 - 正如您所看到的,一個系統表 __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 表已新增到您的資料庫中。

StudentsLogIn

上面提到的自動遷移步驟僅適用於您的實體。例如,要新增另一個實體類或刪除現有實體類,它將成功遷移。但是,如果您向實體類新增或刪除任何屬性,它將引發異常。

步驟 10 - 要處理屬性遷移,您需要在 configuration 類建構函式中設定 AutomaticMigrationDataLossAllowed = true。

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

基於程式碼的遷移

當您開發新應用程式時,您的資料模型會頻繁更改,每次模型更改時,它都會與資料庫不同步。您已將實體框架配置為每次更改資料模型時自動刪除和重新建立資料庫。當您想要更多地控制遷移時,基於程式碼的遷移非常有用。

  • 當您新增、刪除或更改實體類或更改您的 DbContext 類時,下次執行應用程式時,它會自動刪除您現有的資料庫,建立一個與模型匹配的新資料庫,並使用測試資料對其進行填充。

  • 程式碼優先遷移功能透過啟用程式碼優先更新資料庫模式而不是刪除和重新建立資料庫來解決此問題。要部署應用程式,您必須啟用遷移。

以下是遷移資料庫更改的基本規則:

  • 啟用遷移
  • 新增遷移
  • 更新資料庫

讓我們看一下基於程式碼的遷移的分步過程。

當您使用程式碼優先方法時,您的應用程式沒有資料庫。

在這個例子中,我們將再次從三個基本類開始,例如學生、課程和註冊,如下程式碼所示。

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 資料夾中建立了一個新檔案,其名稱是您傳遞給命令的引數加上時間戳字首,如下圖所示。

TimeStamp Prefix

步驟 5 - 您可以使用“update-database”命令建立或更新資料庫。

PM> Update-Database -Verbose

“-Verbose”標誌指定在控制檯中顯示應用於目標資料庫的 SQL 語句。

步驟 6 - 讓我們在學生類中新增另一個屬性“年齡”,然後執行更新語句。

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 已新增到您的資料庫中。

New Column Age.

我們建議您逐步執行上述示例,以便更好地理解。

廣告
© . All rights reserved.