EF Core 提供兩種主要方法來保持 EF Core 模型和資料庫架構同步。至於我們應該選用哪個方法,請確定你是希望以 EF Core 模型為準還是以資料庫為準。 如果希望以 EF Core 模型為準,請使用遷移。 對 EF Core 模型進行更改時,此方法會以增量方式將相應架構更改應用到資料庫, ...
-
如果希望以 EF Core 模型為準,請使用
-
如果希望以資料庫架構為準,請使用
1. 數據遷移
在實際項目中,數據模型隨著功能的實現而變化:添加和刪除新的實體或屬性,並且需要相應地更改資料庫架構,使其與應用程式保持同步。 EF Core 中的遷移功能能夠以遞增方式更新資料庫架構,使其與應用程式的數據模型保持同步,同時保留資料庫中的現有數據。
簡要地說,遷移的方式如下:
-
當引入數據模型更改時,開發人員使用 EF Core 工具添加相應的遷移,以描述使資料庫架構保持同步所需的更新。EF Core 將當前模型與舊模型的快照進行比較,以確定差異,並生成遷移源文件;文件可在項目的源代碼管理中進行跟蹤,如任何其他源文件。
-
生成新的遷移後,可通過多種方式將其應用於資料庫。 EF Core 在一個特殊的歷史記錄表中記錄所有應用的遷移,使其知道哪些遷移已應用,哪些遷移尚未應用。
安裝工具
首先,必須安裝
-
我們通常建議使用
# 安裝 dotnet tool install -g --version 6.0.4 dotnet-ef # 更新 dotnet tool update --global dotnet-ef --version 6.0.7 # 在將工具用於特定項目之前,需要將 Microsoft.EntityFrameworkCore.Design 添加到該項目中。 dotnet add package Microsoft.EntityFrameworkCore.Design --version 6.0.4 dotnet add package Microsoft.EntityFrameworkCore.Tools --version 6.0.4 # 驗證 dotnet ef _/\__ ---==/ \\ ___ ___ |. \|\ | __|| __| | ) \\\ | _| | _| \_/ | //|\\ |___||_| / \\\/\\ Entity Framework Core .NET Command-line Tools 2.1.3-rtm-32065 <Usage documentation follows, not shown.>
常用選項
選項 Short 說明 --json
顯示 JSON 輸出。 --context <DBCONTEXT>
-c
要使用的 DbContext
類。 僅類名或完全限定命名的空間。 如果省略此選項,EF Core 將查找上下文類。 如果有多個上下文類,則此選項是必需的。--project <PROJECT>
-p
目標項目的項目文件夾的相對路徑。 預設值是當前文件夾。 --startup-project <PROJECT>
-s
啟動項目的項目文件夾的相對路徑。 預設值是當前文件夾。 --framework <FRAMEWORK>
--configuration <CONFIGURATION>
生成配置,例如 Debug
或Release
。--runtime <IDENTIFIER>
要為其還原包的目標運行時的標識符。 有關運行時標識符 (RID) 的列表,請參閱 --no-build
請勿生成項目。 旨在在生成處於最新狀態時使用。 --help
-h
顯示幫助信息。 --verbose
-v
顯示詳細輸出。 --no-color
請勿為輸出著色。 --prefix-output
具有級別的首碼輸出。 -
如果你更喜歡在 Visual Studio 內工作或你具有 EF6 遷移經驗,還可以使用
# 安裝 Install-Package Microsoft.EntityFrameworkCore.Tools # 更新 Update-Package Microsoft.EntityFrameworkCore.Tools # 驗證安裝 Get-Help about_EntityFrameworkCore _/\__ ---==/ \\ ___ ___ |. \|\ | __|| __| | ) \\\ | _| | _| \_/ | //|\\ |___||_| / \\\/\\ ......
通用參數
下表顯示了所有 EF Core 命令的通用參數:
參數 說明 -Context <String>
要使用的 DbContext
類。 僅類名或完全限定命名的空間。 如果省略此參數,EF Core 將查找上下文類。 如果有多個上下文類,則此參數是必需的。-Project <String>
目標項目。 如果省略此參數,則包管理器控制台的預設項目將用作目標項目。 -StartupProject <String>
啟動項目。 如果省略此參數,則解決方案屬性中的啟動項目將用作目標項目。 -Args <String>
傳遞給應用程式的參數。 已在 EF Core 5.0 中添加。 -Verbose
顯示詳細輸出。
創建第一個遷移
public class Blog { public int Id { get; set; } public string Name { get; set; } }
你現在已準備好添加第一個遷移! 指示 EF Core 創建名為 InitialCreate 的遷移:
.NET CLI
dotnet ef migrations add InitialCreate
VisualStudio
Add-Migration InitialCreate
EF Core 將在項目中創建一個名為“Migrations”的目錄,並生成一些文件。 最好檢查 EF Core 生成的內容,併在可能的情況下修改它,但現在我們跳過此操作。
創建資料庫和架構
此時,可以讓 EF 創建資料庫並從遷移中創建架構。 可以通過以下操作實現這一點:
.NET CLI
dotnet ef database update
VisualStudio
Update-Database
就是這麼回事 - 你的應用程式已準備好在新資料庫上運行,你無需編寫任何 SQL 代碼。 請註意,這種應用遷移的方法非常適合本地開發,但不太適用於生產環境 - 有關詳細信息,請參閱
發展模型
幾天後,系統會要求你將創建時間戳添加到博客。 你已完成針對應用程式的必要更改,模型現在如下所示:
public class Blog { public int Id { get; set; } public string Name { get; set; } public DateTime CreatedTimestamp { get; set; } }
模型和生產資料庫現在不同步,我們必須向資料庫架構中添加一個新列。 讓我們為此創建新遷移:
.NET CLI
dotnet ef migrations add AddBlogCreatedTimestamp
VisualStudio
Add-Migration AddBlogCreatedTimestamp
請註意,我們為遷移提供了一個描述性名稱,以便以後更容易瞭解項目歷史記錄。
由於這不是項目的第一次遷移,EF Core 現在會在添加列之前將更新的模型與舊模型的快照進行比較;模型快照是 EF Core 在你添加遷移時生成的文件之一,並簽入到源代碼管理中。 基於該比較,EF Core 檢測到已添加一列,並添加適當的遷移。
現在,你可以像以前一樣應用遷移:
.NET CLI
dotnet ef database update
VisualStudio
Update-Database
請註意,這次 EF 檢測到資料庫已存在。 此外,在之前第一次應用遷移時,此事實記錄在資料庫中的特殊遷移歷史記錄表中;這允許 EF 自動僅應用新的遷移。
排除模型的各個部分
備註
EF Core 5.0 中已引入此功能。
有時,你可能希望引用其他 DbContext 中的類型(表)。 這可能會導致遷移衝突。 若要防止出現這種情況,請從 DbContext 之一的遷移中排除該類型。
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<IdentityUser>() .ToTable("AspNetUsers", t => t.ExcludeFromMigrations()); }
命名空間
可以手動移動 Migrations 文件並更改其命名空間。 新建的遷移和上個遷移同級。 或者,可以在生成時指定目錄,如下所示:
.NET CLI
dotnet ef migrations add InitialCreate --output-dir Your/Directory
VisualStudio
Add-Migration InitialCreate -OutputDir Your\Directory
在 EF Core 5.0 中,你還可以使用
-Namespace
獨立於目錄更改命名空間。
刪除遷移
有時,你可能在添加遷移後意識到需要在應用遷移前對 EF Core 模型作出其他更改。 要刪除上個遷移,請使用如下命令。
如果遷移已被應用(執行了 database update),則無法使用remove。
.NET CLI
dotnet ef migrations remove
VisualStudio
Remove-Migration
列出遷移
你可以列出現有的所有遷移,如下所示:
.NET CLI
dotnet ef migrations list
VisualStudio
Get-Migration
重置所有遷移
在某些極端情況下,可能需要刪除所有遷移並重新開始。 這可以通過刪除 Migrations 文件夾並刪除資料庫來輕鬆完成;此時,你可以創建一個新的初始遷移,其中將包含當前的整個架構。
你還可以重置所有遷移並創建單個遷移,而不會丟失數據。 此操作有時稱為“更正”,涉及一些手動操作:
-
刪除 Migrations 文件夾
-
創建新遷移併為其生成 SQL 腳本
-
在資料庫中,刪除遷移歷史記錄表中的所有行
-
在遷移歷史記錄中插入一行,以記錄第一個遷移已經應用,因為表已經存在。 insert SQL 是上面生成的 SQL 腳本中的最後一個操作(在我們刪除了Migrations文件夾中所有的遷移文件以及刪除完_efmigrationshistory表中的記錄之後,再執行一次migrations add 的命令,表示重新添加一條記錄,然後不要執行database update 命令,最後再把剛剛遷移生成的記錄添加至__efmigrationshistory 表中)。
警告
刪除 Migrations 文件夾後,所有
2. 應用遷移
添加遷移後,需要將其部署並應用到資料庫。 有多種策略可用於執行此操作,其中一些更適合生產環境,而另一些更適合開發生命周期。
備註
無論部署策略是什麼,都應檢查生成的遷移併進行測試,然後再將其應用於生產資料庫。 遷移可能會在意圖是對列進行重命名時刪除該列,或者在應用於資料庫時因各種原因而失敗。
SQL 腳本
建議通過生成 SQL 腳本,將遷移部署到生產資料庫。 此策略的優點包括:
-
可以檢查 SQL 腳本的準確性;這一點很重要,因為將架構更改應用於生產資料庫是一項可能導致數據丟失的潛在危險操作。
-
在某些情況下,可以根據生產資料庫的特定需求調整這些腳本。
-
SQL 腳本可以與部署技術結合使用,甚至可以在 CI 過程中生成。
-
SQL 腳本可以提供給 DBA,並且可以單獨管理和存檔。
基本用法
以下命令將生成一個從空白資料庫到最新遷移的 SQL 腳本:
.NET CLI
dotnet ef migrations script
VisualStudio
Script-Migration
3. 反向工程
反向工程是基於資料庫架構搭建實體類型類和 DbContext 類基架的過程。 可使用 EF Core 包管理器控制台 (PMC) 工具的 Scaffold-DbContext
命令或 .NET 命令行介面 (CLI) 工具的 dotnet ef dbcontext scaffold
命令執行這一過程。
先決條件
-
在進行反向工程之前,需要安裝
-
在要搭建基架的項目中安裝
Microsoft.EntityFrameworkCore.Design
的 NuGet 包。 -
還需要為要進行反向工程的資料庫架構安裝適當的
連接字元串
該命令的第一個參數是指向資料庫的連接字元串。 工具將使用此連接字元串來讀取資料庫架構。
引用和轉義連接字元串的方式取決於用於執行命令的 shell。 有關詳細信息,請參閱 shell 的文檔。 例如,PowerShell 要求轉義 $
字元,而不是 \
。
.NET CLI
dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
VisualStudio
Scaffold-DbContext 'Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook' Microsoft.EntityFrameworkCore.SqlServer
指定表
預設情況下,將資料庫架構中的所有表反向工程為實體類型。 可通過指定架構和表來限制對哪些表進行反向工程。
.NET CLI
--schema
選項可用於包含架構中的每個表,而 --table
可用於包含特定表。
若要包含多個表,請多次指定選項:
dotnet ef dbcontext scaffold ... --table Artist --table Album
VisualStudio
-Schemas
選項可用於包含架構中的每個表,而 -Tables
可用於包含特定表。
若要包含多個表,請使用數組:
Scaffold-DbContext ... -Tables Artist, Album
保留名稱
預設情況下,表和列名已修正,以便更好地匹配類型和屬性的 .NET 命名約定。 在 PMC 中指定 -UseDatabaseNames
開關或在 .NET Core CLI 中指定 --use-database-names
選項將禁用此行為,從而儘可能保留原始資料庫名稱。 無效的 .NET 標識符仍將被修正,而合成名稱(如導航屬性)仍將符合 .NET 命名約定。
DbContext 名稱
預設情況下,已搭建基架的 DbContext 類名稱將是尾碼為 Context 的資料庫名稱。 若要指定不同名稱,請在 PMC 中使用 -Context
,在 .NET Core CLI 中使用 --context
。
目錄和命名空間
實體類和 DbContext 類將搭建到項目的根目錄中,並使用項目的預設命名空間。
.NET CLI
可使用 --output-dir
指定在其中為類搭建基架的目錄,並且可使用 --context-dir
將 DbContext 類搭建到與實體類型類不同的目錄中:
dotnet ef dbcontext scaffold ... --context-dir Data --output-dir Models
預設情況下,命名空間將是根命名空間加上項目根目錄下任何子目錄的名稱。 但是,從 EFCore 5.0 開始,可使用 --namespace
覆蓋所有輸出類的命名空間。 還可使用 --context-namespace
僅覆蓋 DbContext 類的命名空間:
dotnet ef dbcontext scaffold ... --namespace Your.Namespace --context-namespace Your.DbContext.Namespace
VisualStudio
可使用 -OutputDir
指定在其中為類搭建基架的目錄,並且可使用 -ContextDir
將 DbContext 類搭建到與實體類型類不同的目錄中:
Scaffold-DbContext ... -ContextDir Data -OutputDir Models
預設情況下,命名空間將是根命名空間加上項目根目錄下任何子目錄的名稱。 但是,從 EFCore 5.0 開始,可使用 -Namespace
覆蓋所有輸出類的命名空間。 還可使用 -ContextNamespace
僅覆蓋 DbContext 類的命名空間。
Scaffold-DbContext ... -Namespace Your.Namespace -ContextNamespace Your.DbContext.Namespace
配套視頻鏈接:課程簡介 (cctalk.com)
海闊平魚躍,天高任我行,給我一片藍天,讓我自由翱翔。