論述一體化 Code First & Database First

EF9, Code First, Database First

歷經多次的 EF Core 評測,自 EF6 ~ EF9。EF6 以前是舊的設計 for .NET Framework;EF7 以後的設計 for NET Core,稱作 EF Core。原本在 EF6- 預設的基本運轉行為到了 EF7+ 完全沒繼承一切重新開始,這一點在 EF9 才意識到。在 EF6, EF7, EF8 版本期間因為 LINQ to SQL 會產生奇怪的 SQL 查詢語法讓 debug 陷入深淵,故策略性的放棄 EF 改用 Dapper

自 EF8+ 開始支援 FromSql, SqlQuery, AsNoTracking, FromSqlRaw, SqlQueryRaw 這些新指令讓 Dapper 的優勢消失。LINQ to SQL 的短板還是在且依然無法關閉。EF Core 又增加 Include 指令可以直接映設最常用的 LEFT OUTTER JOIN。但在實際多人開發上還是直接用原生的 SQL 語法比較可靠。

離題了,回來!

§ 為何要重回 EF Core

與其說重回 EF 懷抱,不如說 Dapper 越用越不愛。它的優勢同時也是它的缺點。Dapper 雖是開源然條件式免費。一些進一步的能力不支援或另開收費的套件。還好 SQL Server 相關資源很足才沒有被間接綁架。Dapper 也跨多種主流資料庫,其實作機制採用 reflection 在執行時期才動態判斷是那一種資料庫再用 if 分支跑對應的 database provider,這讓執行效率其差無比。單一 SQL 指令執行效率差是無感的,跑批次 SQL 指令就很明顯。後來也增加 Dapper.AOT 套件可在 AOT 環境加速,不過支援只做半套進階指令無法執行,本人只好把 AOT 特性撤除不然連基本指令也無法執行。

相應的期間 EF Core 也有進步,新增 FromSql, SqlQuery 等指令讓 Dapper 優勢不在。只是 LINQ to SQL 的困擾看來只能用教育訓練告誡不準用。

為何選擇回頭用 EF Core

一句話:成熟度與完整性。

一、EF Core 有工具程式可以同步 ORM schema。

二、EF Core 週邊與能力完整性。

三、支援多種類型資章庫。

四、仍在進步並會修正路線。

五、是 NET 生態系原生資源之一。

六、痛恨的 LINQ to SQL 雖還在,不過已有相應方案。

不管是 Code First 還是 Database First 都是用 EF Core Tools 協助實作。經數次練習化整為零其實主要就四個指令組合應用。

-- 指令順序(省略細部參數)
-- step 1: 自 DB 同步 scheam。
dotnet ef dbcontext scaffold <connection> <provider> 
  
-- step 2: 自動製作 migration 『schema 差異指令』。
dotnet ef migrations add <name>

-- step 2a: [option] 移除最近一次的 migration,可能不滿意想重作。
dotnet ef migrations remove 

-- step 3: 把最近一次的 migration 送到目標 DB 並執行『schema 差異指令』。
dotnet ef database update

Code First 流程

Code First (define schema) → migration & update
[→ adjust schema → migration & update][…]

或走捷徑 / 一步到位 / 不滿意從頭開始 (※ 走捷徑這條只適合全新的小系統。)

EnsureDeletedEnsureCreated

Database First 流程

Database First (scaffold from DB) → initial migration & update 
[→ adjust schema → migration & update][…]

§ 一體化 Code First 與 Database First

不管用 Code First 還是 Database First 都不符合實際的變化。加入產品生命週期來考慮流程。

一開始是全新的系統。

第一輪 dev. phase,我們需要快速生出原型與畫面給客戶查驗,這時可以走捷徑

EnsureDeletedEnsureCreated

若客戶不愛就重頭來過,直到第一個 milestone 玩成。

第二輪 dev. phase,有些基礎 schema 已定案。那就製作資料庫 initial migration & update

然後進行滿足下階段需求的 adjust schema → migration & update。

又下一輪 dev. phase,重複滿足下階段需求的 adjust schema → migration & update。直到上線。

到這裡都還算是 Code First。

接下來系統上線跑幾個月後。資料庫有些 bug 或 new requirement 可以直接在 DB 內處理,漸漸的漸漸的真實的 DB schema 與 ORM class 已不再同步。

到了專案第二期。

為確保為確保 DB schema 與 ORM class 一致性執行 scaffold from DB 以同步。(database first)

這時最好重新製作 initial migration & update。

然後進行滿足下階段需求的 adjust schema → migration & update。直到第二期上線。

專案第三期。

同第二期的程序週期。值到永遠。

一體化符號表示

把上述專案生命週期有關 schema 的部份用符號表示如下:

// 全新專案
EnsureDeleted → EnsureCreated (code first)
// 第一個 milestone 達成
→ initial migration & update
// 之後覆返精進
→ adjust schema → migration & update [→ adjust schema → migration & update][...] 

// 過一段時間 DB schema 與 ORM class 可能漸行漸遠,
// 執行 scaffold from DB 以確保同步。
scaffold from DB (database first)
// 重製 initial (scaffold) migration
→ initial-scaffold migration & update
// 之後覆返精進
→ adjust schema → migration & update [→ adjust schema → migration & update][...] 

§ 歷次評估

EF9 Database First 再試用紀錄EF9 Code First 試用紀錄EF9 DB first 紀錄EF Core 9 Database First / DB First (Entity Framework Core 9 / .NET 9)EF Core 8 DbContext Scaffold 練習

§ 其他參考文件

(EOF)

Last updated