天天看點

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

使用實體架構 Code First 時,預設行為是使用一組 EF 中内嵌的約定将 POCO 類映射到表。但是,有時您無法或不想遵守這些約定,需要将實體映射到約定訓示外的其他對象。特别是這些内嵌的約定可能和資料庫相關的,對不同的資料庫可能有不同的表示方式,或者我們可能不同資料庫的表名、字段名有所不同;還有就是我們希望盡可能保持POCO類的純潔度,不希望弄得太過烏煙瘴氣的,那麼我們這時候引入Fluent API 配置就很及時和必要了。

上篇随筆裡面我構造了幾個代表性的表結構,具體關系如下所示。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

這些表包含了幾個經典的關系,一個是自引用關系的Role表,一個是User和Role表的多對多關系,一個是User和UserDetail之間的引用關系。

我們看到,預設使用EF工具自動生成的實體類代碼如下所示。

而其生成的資料庫操作上下文類的代碼如下所示。

不管是Code First模式中使用 Fluent API 配置,還是使用了前面的Attribute特性标記的說明,都是為了從代碼層面上建構實體類和表之間的資訊,或者多個表之間一些關系,不過如果我們把這些實體類Attribute特性标記去掉的話,那麼我們就可以通過Fluent API 配置進行屬性和關系的指定了。

其實前面的OnModelCreating函數裡面,已經使用了這種方式來配置表之間的關系了,為了純粹使用Fluent API 配置,我們還需要把實體類進行簡化,最終我們可以獲得真正的實體類資訊如下所示。

這個實體類和我們以往的表現幾乎一樣,沒有多餘的資訊,唯一多的就是完全是實體對象化了,包括了一些額外的關聯對象資訊。

前面說了,Oracle的生成實體類字段全部為大寫字母,不過我們實體類還是需要保持它的Pascal模式書寫格式,那麼就可以在Fluent API 配置進行指定它的字段名為大寫(注意,Oracle一定要指定字段名為大寫,因為它是大小寫敏感的)。

最終我們定義了Oracle資料庫USERS表對應映射關系如下所示。

我們為每一個字段進行了字段名稱的映射,而且Oracle要大寫,我們還通過 ToTable("WHC.USERS") 把它映射到了WHC.USERS表裡面了。

如果對于有多對多中間表關系的Role來說,我們看看它的關系代碼如下所示。

這裡注意的是MapLeftKey和MapRightKey一定的對應好了,否則會有錯誤的問題,一般情況下,開始可能很難了解那個是Left,那個是Right,不過經過測試,可以發現Left的肯定是指向目前的這個映射實體的鍵(如上面的為ROLE_ID這個是Left一樣,因為目前的實體映射是Role對象)。

通過這些映射代碼的建立,我們為每個表都建立了一一的對應關系,剩下來的就是把這映射關系加載到資料庫上下文對象裡面了,還記得剛才說到的OnModelCreating嗎,就是那裡,一般我們加載的方式如下所示。

這種做法代替了原來的臃腫代碼方式。

一般情況下,到這裡我認為基本上把整個思路已經介紹完畢了,不過精益求精一貫是個好事,對于上面的代碼我還是覺得不夠好,因為我每次在加載 Fluent API 配置的時候,都需要指定具體的映射類,非常不好,如果能夠把它們動态加載進去,豈不妙哉。

對類似下面的關系寫死可不是一件好事。

我們可以通過反射方式,把它們進行動态的加載即可。這樣OnModelCreating函數處理的時候,就是很靈活的了,而且OnModelCreating函數隻是在程式啟動的時候映射一次而已,即使重複建構資料庫操作上下文對象DbEntities的時候,也是不會重複觸發這個OnModelCreating函數的,是以我們利用反射不會有後顧之憂,性能隻是第一次慢一點而已,後面都不會重複觸發了。

最終我們看看一步步下來的代碼如下所示(注釋的代碼是不再使用的代碼)。

這樣我們運作程式運作正常,不在受限制于實體類的字段必須是大寫的憂慮了。而且動态加載,對于我們使用其他資料庫,依舊是個好事,因為其他資料庫也隻需要修改一下映射就可以了,真正遠離了複雜的XML和實體類臃腫的Attribute書寫内容,實作了非常彈性化的映射處理了。

最後我貼出一下測試的代碼例子,和前面的随筆使用沒有太大的差異。

測試Oracle資料庫,我們可以發現資料添加到資料庫裡面了。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

而且上面例子也建立了總結表的對應關系,具體資料如下所示。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

如果是SQLServer,我們還可以看到資料庫裡面添加了一個額外的表,如下所示。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

如果表的相關資訊變化了,記得把這個表裡面的記錄清理一下,否則會出現一些錯誤提示,如果去找代碼,可能會發現浪費很多時間都沒有很好定位到具體的問題的。

這個表資訊,在其它資料庫裡面沒有發現,如Oracle、Mysql、Sqlite裡面都沒有,SQLServer這個表的具體資料如下所示。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)

整個項目的結構優化為标準的架構結構後,結構層次如下所示。

Entity Framework 實體架構的形成之旅--Code First模式中使用 Fluent API 配置(6)