3. Migrations


Posted by WayneCheng on 2021-03-30

關於 Migrations 本篇將討論以下幾個問題

1. Migrations 基本操作

2. Migrations 應用


測試環境:

OS:Windows 10
IDE:Visual Studio 2019
MS SQL:SQL Server 2019 Linux
SSMS:Microsoft SQL Server Management Studio 18


1. Migrations 基本操作

以下提供 .NET Core CLI & PowerShell 兩種操作方式,可依據個人習慣使用。

1.1 初次建立 Migrations

EF Core 會在專案中建立名為 Migrations 的目錄,並產生一些相關檔案。

操作方式 語法
.NET Core CLI dotnet ef migrations add InitialCreate
PowerShell Add-Migration InitialCreate

若不想建立在跟目錄,也可透過 -OutputDir 指定目錄位置。

操作方式 語法
.NET Core CLI dotnet ef migrations add InitialCreate --output-dir [指定目錄]
PowerShell Add-Migration InitialCreate -OutputDir [指定目錄]

1.2 新增 Migrations

依據 Context 中註冊的 Model 的變更,與舊有 Migrations 比較產生差異紀錄,每次新增的 Migrations 中包含兩個部分,除了自動產生的部分外也可以自定義所需屬性

  • Up:更新時的操作
  • Down:還原時的操作

    public partial class AddFirstNameAndLastName : Migration
    {
      // 更新時的操作
      protected override void Up(MigrationBuilder migrationBuilder)
      {
          migrationBuilder.AddColumn<string>(
              name: "FirstName",
              table: "Users",
              type: "nvarchar(max)",
              nullable: true);
    
          migrationBuilder.AddColumn<string>(
              name: "LastName",
              table: "Users",
              type: "nvarchar(max)",
              nullable: true);
      }
    
      // 還原時的操作
      protected override void Down(MigrationBuilder migrationBuilder)
      {
          migrationBuilder.DropColumn(
              name: "FirstName",
              table: "Users");
    
          migrationBuilder.DropColumn(
              name: "LastName",
              table: "Users");
      }
    }
    
操作方式 語法
.NET Core CLI dotnet ef migrations add [MigrationName]
PowerShell Add-Migration [MigrationName]

※ [MigrationName] 命名建議依據團隊規範來建立,以便後續管理。

1.3 移除 Migrations

移除前一次 Migration,還未更新至資料庫的話,可以直接刪除 Migrations 目錄中的檔案或是透過語法來刪除。

操作方式 語法
.NET Core CLI dotnet ef migrations remove
PowerShell Remove-Migration

1.4 查詢 Migrations

列出全部 Migrations

操作方式 語法
.NET Core CLI dotnet ef migrations list
PowerShell Get-Migration

1.5 套用至資料庫

以上操作都只是在專案中進行,最後還需要透過 Update 語法與資料庫同步,一般會直接更新至最新版本

操作方式 語法
.NET Core CLI dotnet ef database update
PowerShell Update-Database

1.6 將已存在 Migrations 套用至空白資料庫

操作方式 語法
.NET Core CLI dotnet ef migrations script
PowerShell Script-Migration

2. Migrations 應用

2.1 情境一:使用 SQL 語法

透過 migrationBuilder.Sql 除了範例中簡單的將 FirstName 與 LastName 組合起來之外,還可以透過以下五種複雜操作來處理資料

  • Stored procedures 預存程序
  • Full-Text Search 全文檢索搜尋
  • Functions 函式
  • Triggers 觸發程序
  • Views 檢視
public partial class AddFirstNameAndLastName : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "FirstName",
            table: "Users",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "LastName",
            table: "Users",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.Sql(
            @"
                UPDATE Users
                SET Name = FirstName + ' ' + LastName;
            ");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "FirstName",
            table: "Users");

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

2.2 情境二:欄位刪除的順序

假設原本使用 FirstName & LastName 兩個欄位,而之後想改用 Name 一個欄位來取代。

先刪除欄位再新增欄位,會將舊資料全部刪除,Name 中的資料需要重新建立

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

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

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

可以透過 migrationBuilder.SqlFirstName & LastName 兩個欄位合併後填入 Name 中再刪除

// 透過 SQL 合併兩個欄位資料,處理完後刪除舊欄位
migrationBuilder.AddColumn<string>(
    name: "Name",
    table: "Customer",
    nullable: true);

migrationBuilder.Sql(@"
    UPDATE Users
    SET Name = FirstName + ' ' + LastName;
");

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

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

完整程式碼

GitHub:CodeFirst


總結

操作 Migrations 時只要還沒套用至資料庫都很容易還原,但若是套用至資料庫後就會多了資料面的問題,建議無論動作多簡單,都養成備份資料庫的好習慣,。


參考資料

  1. Entity Framework Core

新手上路,若有錯誤還請告知,謝謝


#EntityFramework







Related Posts

MTR04_1114

MTR04_1114

[Day 06]: Docker Network-2

[Day 06]: Docker Network-2

OOP 12 - Open-Closed Principle

OOP 12 - Open-Closed Principle


Comments