共用方式為


管理移轉

隨著模型的變更,遷移會在正常開發過程中被新增或移除,並且遷移檔案會簽入您專案的版本控制系統。 若要管理移轉,您必須先安裝 EF Core 命令列工具

小提示

如果 DbContext 與啟動項目位於不同的元件中,您可以在 套件管理員主控台工具.NET Core CLI 工具中明確指定目標和啟動專案。

新增移轉

在修改模型後,您可以為該變更新增一個遷移:

dotnet ef migrations add AddBlogCreatedTimestamp

移轉名稱可以像版本控制系統中的認可訊息一樣使用。 例如,如果您針對 Blog 實體新增一個新 CreatedTimestamp 屬性,您可能會選擇一個名稱如 AddBlogCreatedTimestamp

移轉 目錄下,會將三個檔案新增至您的專案:

  • XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.cs--主要移轉檔案。 包含套用遷移所需的操作(在 Up中),以及還原該遷移(在 Down中)。
  • XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.Designer.cs--遷移的元數據檔案。 包含EF所使用的資訊。
  • MyContextModelSnapshot.cs--您目前模型的快照集。 用來判斷新增下一次遷移時有哪些變更。

檔名中的時間戳有助於讓它們依時間順序排序,讓您可以看到變更的進展。

命名空間

您可以自由移動移轉檔案,並手動變更其命名空間。 新的遷移會被建立成為上次遷移的同級。 或者,您可以在產生時間指定目錄,如下所示:

dotnet ef migrations add InitialCreate --output-dir Your/Directory

備註

您也可以使用 --namespace,獨立變更目錄的命名空間。

自定義移轉程序代碼

雖然 EF Core 通常會建立精確的移轉,但您應該一律檢閱程式碼,並確定它對應至所需的變更;在某些情況下,甚至有必要這樣做。

欄重新命名

需要自定義移轉的一個值得注意的範例是重新命名屬性。 例如,如果您將屬性從 Name 重新命名為 FullName,EF Core 將會產生下列移轉:

migrationBuilder.DropColumn(
    name: "Name",
    table: "Customers");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customers",
    nullable: true);

EF Core 通常無法知道何時打算卸除數據行並建立新的數據行(兩個不同的變更),以及何時應該重新命名數據行。 如果套用上述移轉 as-is,則所有客戶名稱都會遺失。 若要重新命名數據行,請使用下列內容取代上述產生的移轉:

migrationBuilder.RenameColumn(
    name: "Name",
    table: "Customers",
    newName: "FullName");

小提示

遷移鷹架程序在某個操作可能導致資料遺失時會發出警告(例如刪除欄位)。 如果您看到該警告,請務必檢查移轉程式碼以確保正確性。

新增原始 SQL

雖然可以透過內建 API 重新命名數據行,但在許多情況下是不可能的。 例如,我們可能想要將現有的 FirstNameLastName 屬性取代為單一的新 FullName 屬性。 EF Core 所產生的移轉如下:

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

和之前一樣,這會導致不必要的數據遺失。 為了從舊欄位傳輸數據,我們會重新排列遷移,並引入原始 SQL 操作,如下所示:

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

migrationBuilder.Sql(
@"
    UPDATE Customer
    SET FullName = FirstName + ' ' + LastName;
");

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

透過原始 SQL 進行任意變更

原始 SQL 也可以用來管理 EF Core 不知道的資料庫物件。 若要這樣做,請新增一個遷移而不進行任何模型變更;系統會產生一個空的遷移,然後您就可以填入原始 SQL 操作。

例如,下列移轉會建立 SQL Server 預存程式:

migrationBuilder.Sql(
@"
    EXEC ('CREATE PROCEDURE getFullName
        @LastName nvarchar(50),
        @FirstName nvarchar(50)
    AS
        RETURN @LastName + @FirstName;')");

小提示

當語句必須是 SQL 批次中的第一個或只有一個時,就會使用 EXEC。 它也可以用來解決數據表上目前不存在參考數據行時可能發生的等冪移轉腳本中的剖析器錯誤。

這可用來管理資料庫的任何層面,包括:

  • 預存程序
  • 全文檢索
  • 功能
  • 觸發器
  • 瀏覽次數

在大部分情況下,EF Core 會在套用移轉時,自動將每個移轉包裝在自己的交易中。 不幸的是,某些資料庫中的某些移轉作業無法在交易中執行,在這些情況下,您可以將 suppressTransaction: true 傳遞至 migrationBuilder.Sql,以退出交易。

移除遷移

有時候,您會新增移轉,並意識到在套用之前必須先對 EF Core 模型進行其他變更。 若要移除最後一個移轉,請使用此命令。

dotnet ef migrations remove

拿掉移轉之後,您可以進行其他模型變更,然後再次新增。

警告

避免移除已套用至生產資料庫的任何移轉。 這樣做表示您將無法從資料庫中回覆這些移轉,並可能會破壞後續移轉所依據的假設。

列出移轉

您可以列出所有現有的移轉,如下所示:

dotnet ef migrations list

檢查待處理的模型變更

備註

此功能是在 EF Core 8.0 加入。

有時候,您可能想要檢查上次移轉之後是否有任何模型變更。 這能協助您知道自己或隊友何時忘記新增移轉。 其中一種方法是使用此命令。

dotnet ef migrations has-pending-model-changes

您也可以使用 context.Database.HasPendingModelChanges()以程式設計方式執行這項檢查。 這可以用來撰寫單元測試,如果忘記新增遷移,測試將會失敗。

重設所有遷移

在某些極端情況下,可能需要移除所有移轉並重新開始。 刪除 移轉 資料夾並卸除資料庫,即可輕鬆完成此作業;此時,您可以建立新的初始移轉,其中包含整個目前的架構。

您也可以重設所有移轉,並建立單一移轉,而不會遺失您的數據。 這有時稱為「壁球」,並牽涉到一些手動工作:

  1. 備份資料庫,萬一發生問題。
  2. 在您的資料庫中,從移轉歷程記錄數據表中刪除所有數據列(例如 SQL Server 上的 DELETE FROM [__EFMigrationsHistory])。
  3. 刪除你的 遷移 資料夾。
  4. 建立新的移轉,併為其產生 SQL 腳本(dotnet ef migrations script)。
  5. 在遷移紀錄中插入一個單一數據列,以記錄首次遷移已經執行,因為您的數據表已經存在。 插入 SQL 是上述產生的 SQL 腳本中的最後一個作業,如下所示(別忘了更新值):
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');

警告

刪除 移轉 資料夾時,任何 自定義移轉程式代碼 都會遺失。 任何自定義項目都必須手動套用至新的初始移轉,才能保留。

其他資源