介紹
EFCore工具可幫助完成設計資料庫時候的開發任務,主要用於通過對資料庫架構進行反向工程來管理遷移和搭建DbContext和實體型別。EFCore .NET命令列工具是對跨平臺.NET Core CLI工具的擴充套件,該工具執行需要具有.NET Core SDK(具有 Sdk="Microsoft.NET.Sdk" 的專案或專案檔案中的相似專案)的專案,優點是適用於所有平臺。
安裝工具
使用終端工具執行在任意目錄執行下面命令,可以嘗試下Terminal終端工具。
# 安裝為全域性工具
dotnet tool install --global dotnet-ef
# 更新工具
dotnet tool update --global dotnet-ef
驗證安裝
dotnet ef
參考地址:https://docs.microsoft.com/zh-cn/ef/core/cli/dotnet
建立專案
本次使用的專案為.NetCore WebAPI專案,程式碼結構如下
遷移程式碼優先
簡單遷移
使用遷移還需要另外安裝Nuget包
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.6" />
在專案資料夾目錄下操作終端工具
dotnet ef migrations add Init
// 指定Migrations目錄
dotnet ef migrations add Init --output-dir MyMigration
// 指定遷移上下文
dotnet ef migrations add Init --context BlogContext
在 EF Core 5.0及以上 中,才可以使用更改獨立於目錄的名稱空間 --namespace 。
此處Init為遷移名稱,該名稱要可以表示出當前遷移的內容資訊。
生成成功,檢視專案內的變化,增加了一個資料夾Migrations
xxxxxx_Init -主遷移檔案。包含應用遷移的操作(在up中)和還原遷移所需的操作(在down中)
OpenDbContextModelSnapshot -當前模型的快照。用於確定新增下一遷移時的更改內容。
最好檢查下生成的內容是不是我們期望的那樣子,有些情況下是需要進行修改的。
如果這個時候,我們又修改了實體類,那麼還可以執行命令再次遷移(遷移名稱不能相同)
特殊情況
有些特殊情況下生成的遷移檔案不是我們預期的那樣子,這個時候需要手動修改。
列名重新命名
如果實體類中的列明重複了,我們重新遷移,檢視生成的檔案,比如我將使用者表Account修改為UserName,按照官網的說法會生成一下遷移
migrationBuilder.DropColumn(
name: "Account",
table: "User");
migrationBuilder.AddColumn<string>(
name: "UserName",
table: "User",
nullable: true);
實際生成結果為
migrationBuilder.RenameColumn(
name: "Account",
table: "user",
newName: "UserName");
如果生成了先Drop再Add那種進行應用資料庫,則使用者的帳號都會丟失,所以需要修改我下面這種。(當前現在生成的就是我們想要樣子,不過我們還需要謹慎)
還有其他的情況需要注意,可以參考官網
刪除遷移
有時候我們在新增遷移後,馬上有實體進行改動,這個時候我們並不像再次生成遷移,那麼就可以考慮刪除上個遷移。
dotnet ef migrations remove
刪除遷移後,對實體進行更改,然後再次新增遷移。特殊情況下我們想刪除所有的遷移,可以通過刪除遷移資料夾並刪除資料庫來完成。
場景:我們已經生成了許多遷移檔案,比較繁瑣,我們想將這些遷移檔案合併,那麼就可以刪除遷移資料夾,然後刪除資料庫的遷移歷史表資料,再次生成遷移,根據生成的遷移名稱,對遷移歷史記錄表增加一條對應的資料。
列出遷移
通過下面命令可以查詢到我們所有的遷移
dotnet ef migrations list
生成SQL指令碼
生成從0到最新遷移的SQL指令碼
dotnet ef migrations script
From
生成從給定遷移到最新遷移的SQL指令碼(包含最新遷移)
dotnet ef migrations script AddNewTables
From和To
可以從指定的From遷移到指定遷移To的SQL指令碼
dotnet ef migrations script AddNewTables AddAuditTable
指令碼生成接受以下兩個引數,以指示應生成的遷移範圍:
- from 遷移應是執行該指令碼前應用到資料庫的最後一個遷移。 如果未應用任何遷移,請指定
0
(預設值)。 - to 遷移是執行該指令碼後應用到資料庫的最後一個遷移。 它預設為專案中的最後一個遷移。
建立資料庫和表
手動執行
讓EFCore建立資料庫並從遷移中建立表結構,執行命令
dotnet ef database update
如果後續我們實體類結構再有修改,那麼還可以先建立遷移檔案,然後再生成到資料庫。(因為EF已經檢測到資料庫已存在,會通過對位元殊遷移歷史記錄表,然後只應用那些新的遷移)。
執行時候執行
//如果當前資料庫不存在按照當前 model 建立,如果存在則將資料庫調整到和當前 model 匹配
dbContext.Database.Migrate(); // 生產環境使用考慮好資料問題
請勿在 Migrate() 前呼叫 EnsureCreated()。 EnsureCreated() 會繞過遷移建立架構,這會導致 Migrate() 失敗
建立和刪除API
EnsureDeleted
EnsureDeleted 方法會刪除資料庫(如果存在)。 如果你沒有相應的許可權,則會引發異常。
// Drop the database if it exists
dbContext.Database.EnsureDeleted();
EnsureCreated
如果資料庫不存在,EnsureCreated 將建立資料庫並初始化資料庫架構。 如果存在任何表 (包括其他 DbContext 類) 的表,則不會初始化該架構。
// Create the database if it doesn't exist
dbContext.Database.EnsureCreated();
SQL 指令碼
若要獲取 EnsureCreated 使用的 SQL,可以使用 GenerateCreateScript 方法。
var sql = dbContext.Database.GenerateCreateScript();
多個 DbContext 類
EnsureCreated 僅在資料庫中不存在任何表時有效。 如果需要,您可以編寫自己的檢查來檢視是否需要初始化架構,並使用基礎 IRelationalDatabaseCreator 服務來初始化架構。
// TODO: Check whether the schema needs to be initialized
// Initialize the schema for this DbContext
var databaseCreator = dbContext.GetService<IRelationalDatabaseCreator>();
databaseCreator.CreateTables();
參考地址:https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/ensure-created
反向工程資料庫優先
dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
配置資料庫連線字串、資料庫提供程式
常用配置
--table 指定表反向工程
--context 指定上下文
-context-dir 指定上下文目錄
--output-dir Models 指定上下文目錄
示例:當前我們有一個資料庫檔案,需要通過反向工程生成實體類,表結構如下
user
score
專案結構如下
專案目錄使用終端執行命令
dotnet ef dbcontext scaffold "Server=localhost;Database=test;Port=3306;charset=utf8;uid=root;pwd=123456;" Pomelo.EntityFrameworkCore.MySql --output-dir Entity --context OpenDbContext
專案結構如下
不過反向工程這種並不會將資料庫表註釋帶到程式碼中,並且每次執行時候會刪除原來的表結構。
參考文件
開始遷移:https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/managing?tabs=dotnet-core-cli
自定義歷史記錄表:https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/history-table