套用移轉

新增移轉之後,必須部署並套用至您的資料庫。 有各種策略可以執行這項操作,有些策略更適合生產環境,而另一些則適用於開發生命週期。

注意

無論您的部署策略為何,請一律檢查產生的移轉,並在套用至生產資料庫之前進行測試。 移轉可能會在意圖重新命名數據行時卸除數據行,或因套用至資料庫的各種原因而失敗。

SQL 指令碼

將移轉部署至生產資料庫的建議方式,就是產生 SQL 指令碼。 此策略的優點如下:

  • 您可以檢閱 SQL 指令碼是否正確;這樣做很重要,因為將結構描述變更套用至生產資料庫,這是可能涉及資料遺失的潛在危險作業。
  • 在某些情況下,可以調整指令碼以符合生產資料庫的特定需求。
  • SQL 指令碼可與部署技術搭配使用,甚至可以在 CI 過程中產生。
  • SQL 指令碼可以提供給 DBA,而且可以分開管理和封存。

基本使用方式

下列作業會從空白資料庫產生 SQL 腳稿到最新的移轉:

dotnet ef migrations script

使用 From (隱含)

下列作業會產生從指定移轉至最新移轉的 SQL 腳本。

dotnet ef migrations script AddNewTables

使用 From 與 To

下列會從指定的 from 移轉產生 SQL 腳本到指定的 to 移轉。

dotnet ef migrations script AddNewTables AddAuditTable

您可以使用比 to 新的 from 來產生復原指令碼。

警告

請注意,可能會發生資料遺失的狀況。

腳本產生會接受下列兩個自變數,以指出應該產生哪一個移轉範圍:

  • 執行指令碼之前,from 移轉應該是套用到資料庫的最後一個移轉。 若未套用任何移轉,請指定 0 (此為預設)。
  • 執行指令碼之後,to 移轉是套用到資料庫的最後一個移轉。 預設為您專案中的最後一個移轉。

等冪 SQL 腳本

上述產生的 SQL 腳本只能套用,將架構從一個移轉至另一個移轉;您必須負責適當地套用腳本,並只套用至處於正確移轉狀態的資料庫。 EF Core 也支援產生 等冪 腳本,此腳本會在內部檢查已套用的移轉(透過移轉歷程記錄數據表),並只套用遺漏的移轉。 如果您不完全知道最後套用至資料庫的數據移轉,或部署至可能位於不同移轉中的多個資料庫,這非常有用。

下列會產生等冪移轉:

dotnet ef migrations script --idempotent

命令列工具

EF 命令行工具可用來將移轉套用至資料庫。 雖然在本機開發和測試移轉方面具有生產力,但這種方法不適合管理生產資料庫:

  • SQL 命令會由工具直接套用,而不需要讓開發人員有機會檢查或修改它們。 這在生產環境中可能很危險。
  • .NET SDK 和 EF 工具必須安裝在生產伺服器上,而且需要專案的原始程式碼。

注意

每個移轉都會在自己的交易中套用。 請參閱 GitHub 問題 #22616 ,以討論此領域的可能未來增強功能。

下列會將資料庫更新為最新的移轉:

dotnet ef database update

下列會將資料庫更新為指定的移轉:

dotnet ef database update AddNewTables

請注意,這也可以用來回復到先前的移轉。

警告

請注意,可能會發生資料遺失的狀況。

如需透過命令行工具套用移轉的詳細資訊,請參閱 EF Core 工具參考

移轉套件組合是單一檔案可執行檔,可用來將移轉套用至資料庫。 它們解決了 SQL 文稿和命令列工具的一些缺點:

  • 執行 SQL 文稿需要額外的工具。
  • 這些工具的交易處理和繼續錯誤行為不一致,有時非預期。 如果套用移轉時發生失敗,這可能會讓您的資料庫處於未定義的狀態。
  • 套件組合可以做為 CI 程式的一部分產生,並在稍後輕鬆地在部署程式中執行。
  • 您可以執行套件組合,而不需安裝 .NET SDK 或 EF 工具(或甚至是獨立式的 .NET 運行時間),而且不需要專案的原始程式碼。

下列會產生套件組合:

dotnet ef migrations bundle

下列會產生適用於 Linux 的自封套件組合:

dotnet ef migrations bundle --self-contained -r linux-x64

如需建立套件組合的詳細資訊,請參閱 EF Core 工具參考

efbundle

產生的可執行文件預設會命名 efbundle 。 它可用來將資料庫更新為最新的移轉。 它相當於執行 dotnet ef database updateUpdate-Database

引數:

Argument 描述
<MIGRATION> 目標移轉。 如果為 '0',則會還原所有移轉。 預設為上次移轉。

選項:

選項 Short 描述
--connection <CONNECTION> 資料庫的連接字串。 預設為 AddDbContext 或 OnConfiguring 中指定的 。
--verbose -v 顯示詳細信息輸出。
--no-color 不要將輸出著色。
--prefix-output 具有層級的前置詞輸出。

下列範例會使用指定的使用者名稱和密碼,將移轉至本機 SQL Server 實例。

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword'

警告

別忘了複製 appsettings.json 與套件組合。 套件組合仰賴執行目錄中 appsettings.json 的存在。

移轉套件組合範例

套件組合需要移轉才能包含。 這些是使用 dotnet ef migrations add 建立您的第一個移轉中所述建立。 當您準備好部署移轉之後,請使用 dotnet ef migrations bundle建立套件組合。 例如:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

輸出是適合目標作業系統的可執行檔。 在此情況下,這是 Windows x64,所以我會在本機資料夾中取得 efbundle.exe 卸除。 執行此可執行檔案會套用其內含的移轉:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>

dotnet ef database update如同 或 Update-Database,只有在尚未套用移轉時,才會將移轉套用至資料庫。 例如,再次執行相同的套件組合不會執行任何動作,因為沒有要套用的新移轉:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>

不過,如果對模型進行變更,並使用 產生 dotnet ef migrations add更多移轉,則這些變更可以組合成可套用的新可執行檔。 例如:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add SecondMigration
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add Number3
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle --force
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

提示

選項 --force 可用來以新的套件組合覆寫現有的套件組合。

執行這個新的套件組合會將這兩個新的移轉套用至資料庫:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

根據預設,套件組合會使用應用程式組態中的資料庫 連接字串。 不過,您可以藉由在命令行上傳遞 連接字串 來移轉不同的資料庫。 例如:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe --connection "Data Source=(LocalDb)\MSSQLLocalDB;Database=SixOhProduction"
Applying migration '20210903083845_MyMigration'.
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

注意

這次會套用這三個移轉,因為它們都尚未套用至生產資料庫。


在執行階段套用移轉

應用程式本身可能會以程式設計方式套用移轉,通常是在啟動期間。 雖然在本機開發和測試移轉方面具有生產力,但這種方法不適合管理生產資料庫,原因如下:

  • 如果應用程式的多個實例正在執行,這兩個應用程式可能會嘗試同時套用移轉並失敗(或更糟的是,造成數據損毀)。
  • 同樣地,如果應用程式在另一個應用程式移轉資料庫時存取資料庫,這可能會導致嚴重問題。
  • 應用程式必須具有較高的存取權,才能修改資料庫架構。 通常最好限制應用程式在生產環境中的資料庫許可權。
  • 在發生問題時,請務必能夠復原已套用的移轉。 其他策略可輕易且立即提供。
  • SQL 命令會直接由程式套用,而不需要讓開發人員有機會檢查或修改它們。 這在生產環境中可能很危險。

若要以程式設計方式套用移轉,請呼叫 context.Database.Migrate()。 例如,典型的 ASP.NET 應用程式可以執行下列動作:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }

    host.Run();
}

請注意, Migrate() 建置在服務之上 IMigrator ,可用於更進階的案例。 您可以使用 myDbContext.GetInfrastructure().GetService<IMigrator>() 來加以存取。

警告

  • 在生產環境中使用此方法之前,請先仔細考慮。 經驗顯示,此部署策略的簡單性已超過其建立的問題。 請考慮改為從移轉產生 SQL 腳本。
  • 請勿在 Migrate() 之前呼叫 EnsureCreated()EnsureCreated() 會略過移轉而建立結構描述,因此造成 Migrate() 失敗。