管理移轉

隨著模型變更,移轉會隨著一般開發而新增和移除,而移轉檔案會簽入您專案的原始檔控制。 若要管理移轉,您必須先安裝 EF Core 命令列工具

提示

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

新增移轉

在模型變更之後,您可以新增該變更的移轉:

dotnet ef migrations add AddBlogCreatedTimestamp

您能夠以類似版本控制系統中認可訊息的方式來使用移轉名稱。 例如,如果變更是實體上的 BlogCreatedTimestamp 屬性,您可能會選擇類似 AddBlogCreatedTimestamp 的名稱。

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

  • XXXXXXXXXXXXXX_AddCreatedTimestamp.cs --主要移轉檔案。 包含套用移轉 (在 Up 中) 及予以反轉 (在 Down 中) 的必要作業。
  • XXXXXXXXXXXXXX_AddCreatedTimestamp.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 通常無法知道何時打算卸載資料行並建立新的資料行(兩個不同的變更),以及何時應該重新命名資料行。 如果上述移轉依情況套用,則所有客戶名稱都會遺失。 若要重新命名資料行,請使用下列內容取代上述產生的移轉:

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

提示

當作業可能導致資料遺失時 (例如卸除資料行),移轉建立程序會引發警告。 如果您看到該警告,請務必檢閱移轉程式碼的正確性。

新增原始 SQL

雖然可以透過內建 API 重新命名資料行,但在許多情況下是不可能的。 例如,我們可能想要以單一的新 FullName 屬性取代現有的 FirstNameLastName 屬性。 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;')");

提示

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

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

  • 預存程序
  • 全文檢索搜尋
  • 函式
  • 觸發程序
  • 檢視

在大部分情況下,EF Core 會在套用移轉時,自動將每個移轉包裝在自己的交易中。 不幸的是,某些移轉作業無法在某些資料庫中的交易內執行;在這些情況下,您可以藉由傳遞 suppressTransaction: truemigrationBuilder.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() 以程式設計方式執行這項檢查。 這可用來撰寫在忘記新增移轉時失敗的單元測試。

重設所有移轉

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

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

  1. 備份資料庫,萬一發生問題。
  2. 在您的資料庫中,從移轉記錄資料表中刪除所有資料列(例如 DELETE FROM [__EFMigrationsHistory] 在 SQL Server 上)。
  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>');

警告

刪除 Migrations 資料夾時,任何 自訂移轉 程式碼 都會 遺失。 任何自訂專案都必須手動套用至新的初始移轉,才能保留。

其他資源