使用 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()
方法來初始資料庫中的資料:
- DbMigrationsConfiguration<TContext>.Seed()
- DropCreateDatabaseIfModelChanges<TContext>.Seed()
- DropCreateDatabaseAlways<TContext>.Seed()
- CreateDatabaseIfNotExists<TContext>.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 團隊計畫會在近期處理它們。
實用連結
- 將應用程式從 EF6 移動到 EF Core
- EF Core 移轉:植入資料 GitHub issue
- Lifecycle Hooks GitHub issue
- EF Core Roadmap
本文翻譯自 Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0
若對以上技術及產品有任何問題,很樂意為您服務! 請洽:台灣微軟開發工具服務窗口 – MSDNTW@microsoft.com / 02-3725-3888 #4922