Entity Framework Code First 利用一種被稱為約定(Conventions)優於配置(Configuration)的編程模式允許你使用自己的 domain classes 來表示 EF 所依賴的模型去執行查詢、更改追蹤、以及更新功能,這意味着你的 domain classes 必須遵循 EF 所使用的約定。然而,如果你的 domain classes 不能遵循 EF 所使用的約定,此時你就需要有能力去增加一些配置使得你的 classes 能夠滿足 EF 所需要的信息。
Code First 提供了兩種方式來配置你的類:
- DataAnnotations, 使用簡單屬性;
- Fluent API, 以編程命令行式的方式來描述你的配置
本文將關注 DataAnnotations(位於命名空間 System.ComponentModel.DataAnnotations)
為了便於示例,我們先創建兩個類:Blog 和 Post
以上類都是遵循約定的,但是你也可以使用 annotations 為 EF 提供更多的信息
Key主鍵
EF 依賴於每一個實體都有一個主鍵從而能夠追蹤實體。 在約定下,主鍵是通過尋找名稱為 ID 或 ClassName + ID 的屬性確定。那么如果類中沒有此類的屬性呢?我們把類改造如下(把 Id 改為 PrimaryTrackingKey)
此時如果我們添加 Scaffolded 會出現如下錯誤
我們需要使用 key annotation 確定哪一個屬性是主鍵
我們使用 Code First's Database Generation 功能看看數據庫的情況
Required非空
用於指示字段非空
運行看一下結果
我們在看一下后台數據庫情況
MaxLength and MinLength長度限制
顧名思義,就是限制字段的長度
看一下后台數據庫
運行看結果
NotMapped忽略
類中有些屬性,如通過計算獲得或其它列的合並而來的,我們並不希望其記錄在數據庫中,此時就可以使用 NotMapped Annotation
對於類也是一樣的
ComplexType復雜類型
一般這種情況是不常見的:類中包含另一個類即一個完整的實體是由一系列類的集合來描述。例如我們在我們的模型中增加一個叫 BlogDetails 的類
注意 BlogDetails 不包含任何主鍵屬性, 在領域驅動設計中被稱為值對象,而在 EF 中則被稱為復雜類型(ComplexType). Complex Types 是無法自我追蹤的,但是我們可以通過 ComplexType Annotation 來改變這種尷尬
可以看到,在數據庫中表 Blog 包含 BlogDetails 的所有兩個屬性,默認列名前綴為 complex type 即 BlogDetails
ConcurrencyCheck並發檢查
ConcurrencyCheck Annotation 允許你可以在一個或多個屬性上設置一個標記用於當用戶更新或刪除實體時做並發檢查。
如果此時同時對此列進行更新,則會拋出異常 DbUpdateConcurrencyException
TimeStamp時間戳
通常用行版本號或時間戳來檢查並發,除了使用 ConcurrencyCheck Annotation, 還可以使用更為精確的 TimsStamp, 前提是這個屬性的類型是字節數組(byte array). Code First 在對待 TimsStamp 屬性和 ConcurrencyCheck 屬性是一樣的,只不過能確保數據庫中生成的字段是 non-nullable
在一個給定的類中只能有一個 TimsStamp 屬性
看一下后台數據庫
Table and Column表/列名
指定匹配到數據庫的表/列名
可以看到表/列名已更改
DatabaseGenerated自增長
DatabaseGeneratedOption 有三個選項:
- DatabaseGeneratedOption.Computed: 在用 Code First 生成數據庫的時候你可以在 byte 或 timestamp 列上使用 DatabaseGenerated Annotation,否則就應該在數據庫存在的情況下使用因為如果數據庫不存在,此時 Code First 不知道為計算列(Computed Column)選擇使用什么樣的公式
- DatabaseGeneratedOption.Identity: 如果主鍵為 integer 型,則數據庫默認為自增長(效果等同於設置DatabaseGeneratedOption.Identity), 如果主鍵是 GUID 類型,則要顯式設置自增長
- DatabaseGeneratedOption.None: 如果不想自增長,可設置成 DatabaseGeneratedOption.None
ForeignKey 外鍵
看看數據庫
InverseProperty屬性反轉
InverseProperty 一般使用在當類間有多重關系的時候。
例如在 Post 中你可能不僅需要追蹤誰寫的也還要追蹤有誰編輯了博客
此時你會看到后台數據庫有四個外鍵 Person_Id, Person_Id1, CreatedBy_Id and UpdatedBy_Id
為了解決這個問題,我們可以使用 InverseProperty annotation 來明確屬性間的指向
再一次看看數據庫,情況已經發生了變化