使用 EF Core 1.0 實作 Seeding、自定義慣例與攔截器

這篇貼文是 .NET 團隊中的軟體工程師 Alina Popa 撰寫的。
 

簡介

Entity Framework Core(EF Core)是一個輕量且可延伸的 Entity Framework(EF)版本,它跨平台而且支援多個資料庫供應商。您可以在 Entity Framework 文件中找到 EF Core 與 EF6 的比較。

當您把一個應用程式從 EF6 移到 EF Core,會遇到一些原來存在於 EF6 的功能,卻沒有出現或還沒有在 EF Core 實作。不過,還是有辦法在 EF Core 中實作出同等的功能。

 

Seeding

在 EF6 時,可以透過覆寫底下其中一個 Seed() 方法來初始資料庫中的資料:

EF Core 沒有提供相似的 API,因為資料庫初始設定已經不在 EF Core 中了。想要初始資料庫,則應該把資料庫初始化程式碼放到應用程式的 startup。如果您在使用移轉(migration),呼叫 context.Database.Migrate(),否則使用 context.Database.EnsureCreated()/EnsureDeleted()

初始化資料庫的模式在 Entity Framework Core 的 GitHub repo 中的 issue 3070 討論。建議的實作方式是在 Startup.Configure() 當中的 Service Scope 執行資料庫初始化程式碼:

您可以在這裡找到一個使用移轉的資料庫初始化例子。MusicStore 範例也是使用這種植入的模式。

請注意,一般而言建議手動採用這些操作(而不要在 startup 自動執行移轉與初始化),避免多個伺服器的競態條件,與無意的更動。

 

自定義慣例

在 Entity Framework 6 我們可以透過使用 model-based 的慣例,建立自定義的屬性與表格配置。例如,以下的程式碼在 EF6 建立一個慣例,當欄位名稱超過 30 個字元,會擲回例外狀況。

EF Core 沒有提供 IStoreModelConvention 介面,然而我們可以透過訪問內部服務來建立慣例(在 EF Core 延伸較低層的元件)。在以下的例子,我們實作了一個 model 的驗證程式,檢查太長的表格或欄位名稱:

請注意這個 model 不是唯讀的,它可以在迴圈內更改。

 

攔截器

Entity Framework 6 使用 IDbCommandInterceptor,提供了攔截內容的能力。攔截器就在指令或查詢送到資料庫前與送到後,讓您進入管道。 Entity Framework Core 目前還沒有任何攔截器,但是可以透過匯入攔截器相關的功能子集來達到,例如 DbContext.SaveChanges

關於上面這個範例:

  • 呼叫 ChangeTracker.DetectChanges() 是為了確保變更追蹤器有在注意實體的改動,例如:如果您設定 .Category 到一個在現存 Product 上新的 Category,新的 Category 將不會被追蹤直到 DetectChanges() 被呼叫或它明確地透過 DbSet 或 ChangeTracker 新增。
  • 在呼叫 base.SaveChanges 之前,將 AutoDetectChangesEnabled 設定為 false 是因為效能的原因,為了避免再呼叫 DetectChanges()。

攔截器與 seeding 在功能待辦項目中的優先度是很高的,而 Entity Framework 團隊計畫會在近期處理它們。

 

實用連結

 

本文翻譯自 Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0


若對以上技術及產品有任何問題,很樂意為您服務! 請洽:台灣微軟開發工具服務窗口 – MSDNTW@microsoft.com / 02-3725-3888 #4922