目錄
1.前言
2.約定
2.1 主鍵約定
2.2 關系約定
2.3 復雜類型約定
3.數據注釋
3.1 主鍵
3.2 必需
3.3 MaxLength和MinLength
3.4 NotMapped
3.5 復雜屬性
3.6 ConcurrencyCheck
4.Fluent API
5.總結
前言
在之前的Code First示例中,我們編寫好代碼直接運行,就自動會自定創建數據庫,並且根據定義好的類創建了對應的表,更加神奇的時候竟然還能自動創建主鍵、外鍵等等。這是如何實現的呢?如果我們想指定特定的屬性為主鍵又該如何實現呢?
約定
其實Code First生成模型的時候會通過約定(Conventions)來檢測,約定實際上是EF定義的一組規則集,用於在使用Code First時根據這些規則生成模型,是在System.Data.Entity.ModelConfiguration.Convertions命名空間中定義的,我們可以去擴展約定,當然也可以不是使用內置的約定。EF內置約定如下:
從上圖我們可以看到定義了復雜屬性預定、外鍵預定、主鍵約定,當然還有很多很多,EF也一直擴充內置約定。
主鍵約定
如果類的屬性名為“ID”(不區分大小寫)或者類名的后面跟有“ID”,則Code First會推斷該屬性是主鍵。如果主鍵屬性的類型為數值或者GUID,則將其配置為標識列。
如上圖所示,DepartmentID會被約定為主鍵。
關系約定
如果類A中的屬性中包含他類B的屬性(該屬性在類B本身中約定為主鍵),並且類A中包含類B,則Code First會自動推斷出關聯關系,並確定外鍵。
如上圖所示,在DepartmentID在Course表中會定義為外鍵,並且Department表和Course表會自動建立關聯關系。
復雜類型約定
當Code First無法推斷出主鍵,並沒有通過其他方式設置主鍵,則該類型會被自動當做復雜屬性。對於以下類定義,Code First推斷Details是復雜屬性,因為它沒有主鍵。
更多參考:https://msdn.microsoft.com/zh-cn/library/jj679962(v=vs.113).aspx
數據注釋
默認情況下,Code First會根據約定定義模型,但是默認的約定規則畢竟有限,Code First同樣允許通過數據注釋來定義模型,而且如果沒有移除約定的話,會先通過約定定義,再通過數據注釋來定義,那么數據注釋是如何實現的呢?
主鍵
類中需要通過數據注釋來定義主鍵,非常簡單,只需要在對應的屬性上面加上KEY關鍵字,如下所示:
必需
屬性上面加上Requied關鍵字,說明這個屬性是必需的,即不允許為空。
MaxLength和MinLength
使用MaxLength和MinLength特性,可以限定字段的范圍。
上圖定義BloggerName長度為5-10。
NotMapped
不映射,顧名思義就是不會將類的屬性映射到數據庫表的字段上,標記了NotMapped特性不會在數據庫表中生成對應的字段。
復雜屬性
在類名上面增加ComplexType特性,並且其他類中某屬性為該類時,該類映射到數據時就會變成復雜屬性。
Blog類中添加一個屬性為BlogDetails。
public BlogDetails BlogDetail { get; set; }
ConcurrencyCheck
ConcurrencyCheck注釋可用於標記要在用戶編輯或刪除實體時用於在數據庫中進行並發檢查的一個或多個屬性。
調用 SaveChanges 時,因為 BloggerName 字段上具有 ConcurrencyCheck 注釋,所以在更新中將使用該屬性的初始值。該命令將嘗試通過同時依據鍵值和 BloggerName 的初始值進行篩選來查找正確的行。下面是發送到數據庫的 UPDATE 命令的關鍵部分,在其中您可以看到該命令將更新 PrimaryTrackingKey 為 1 且 BloggerName 為“Julie”(這是從數據庫中檢索到該博客時的初始值)的行。
如果在此期間有人更改了該博客的博主姓名,則此更新將失敗,並引發 DbUpdateConcurrencyException 並且需要處理該異常。
更多參考:https://msdn.microsoft.com/zh-cn/library/jj591583(v=vs.113).aspx
Fluent API
Code First模式下,默認行為是使用一組EF內嵌的約定規則將類映射到表。但有時候約定無法滿足需求,這是我們還可以通過數據注釋的方式來實現,但是數據注釋功能仍然有限,好在EF提供了更加靈活的方式——Fluent API。
Fluent API功能非常強大,它在通過重寫DbContext上的OnModelCreating方法來實現自定義規則,可以設置主鍵、組合主鍵、外鍵、指定長度、指定屬性是否映射到表等等。
更多參考:https://msdn.microsoft.com/zh-cn/library/jj591617(v=vs.113).aspx
總結
既然EF內置了很多約定規則,為何又可以通過數據注釋方式來定義模型,而且還可以通過功能更加強大的Fluent API自定義模型。
雖然內置的約定規則非常多,而且我想微軟以后還會不斷加入更多的約定,但是這些約定畢竟還是有限的,不能夠滿足所有用戶需求,所以允許通過數據注釋的方式來增加定義模型,但是有些情況通過數據注釋依然是無法滿足(例如:一個類型生成一張表還是多張表),這是我們可以通過Fluent API在生成模型之前自定義模型。
綜上所述,我們得知這三種定義模型的優先級為:約定—>數據注釋—>Fluent API。