天天看點

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

在前面幾篇關于Entity Framework 實體架構的介紹裡面,已經逐漸對整個架構進行了一步步的演化,以期達到統一、高效、可重用性等目的,本文繼續探讨基于泛型的倉儲模式實體架構方面的改進優化,使我們大家能夠很好了解其中的奧秘,并能夠達到通用的項目應用目的。本篇主要介紹實體資料模型 (EDM)的處理方面的内容。

前面第一篇随筆,我在介紹EDMX檔案的時候,已經介紹過實體資料模型 (EDM),由三個概念組成:概念模型由概念架構定義語言檔案 (.csdl)來定義;映射由映射規範語言檔案 (.msl);存儲模型(又稱邏輯模型)由存儲架構定義語言檔案 (.ssdl)來定義。

這三者合在一起就是EDM模式。EDM模式在項目中的表現形式就是擴充名為.edmx的檔案。這個檔案本質是一個xml檔案,可以手工編輯此檔案來自定義CSDL、MSL與SSDL這三部分。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

CSDL定義了EDM或者說是整個程式的靈魂部分 – 概念模型。這個檔案完全以程式語言的角度來定義模型的概念。即其中定義的實體、主鍵、屬性、關聯等都是對應于.NET Framework中的類型。

SSDL這個檔案中描述了表、列、關系、主鍵及索引等資料庫中存在的概念。

MSL這個檔案即上面所述的CSDL與SSDL的對應,主要包括CSDL中屬性與SSDL中列的對應。

我們在編譯程式的時候,發現EDMX檔案并沒有生成在Debug目錄裡面,而EF架構本身是需要這些對象的映射關系的,那肯定就是這些XML檔案已經通過嵌入檔案的方式加入到程式集裡面了,我們從資料庫連接配接的字元串裡面也可以看到端倪。

我們看到,這裡面提到了csdl、ssdl、msl的檔案,而且這些是在資源檔案的路徑,我們通過反編譯程式集可以看到,其實是确實存在這三個檔案的。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

但是我們并沒有把edmx檔案進行拆分啊,而且也沒有把它進行檔案的嵌入處理的啊?有點奇怪!

我們知道,一般這種操作可能是有針對性的自定義工具進行處理的,我們看看這個檔案的屬性進行了解下。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

這個edmx檔案的屬性,已經包含了【自定義工具】,這個工具應該是生成對應的資料通路上下文類代碼和實體類代碼的了,那麼生成操作不是編譯或者内容,而是EntityDeploy是什麼處理呢,我們通過搜尋了解下。

EntityDeploy操作:一個用于部署 Entity Framework 項目的生成任務,這些項目是依據 .edmx 檔案生成的。 可将這些項目作為資源嵌入,或将這些項目寫入檔案。

根據這句話,我們就不難解釋,為什麼編譯後的程式集自動嵌入了三個csdl、ssdl、msl的xml檔案了。

如果我們想自己建構相關的資料通路上下文類,以及實體類的代碼生成(呵呵,我想用自己的代碼生成工具統一生成,可以友善調整注釋、命名、位置等内容),雖然可以調整T4、T5模闆來做這些操作,不過我覺得那個模闆語言還是太啰嗦和複雜了。

這樣我把這個自定義工具【EntityModelCodeGenerator】置為空,也就是我想用自己的類定義格式,自己的生成方式去處理。當置為空的時候,我們可以看到它自動生成的類代碼删除了,呵呵,這樣就挺好。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

在前面的例子裡面,我們都是以預設SqlServer資料庫為例進行介紹EDMX檔案,這個檔案是映射的XML檔案,是以對于不同的資料庫,他們之間的映射内容是有所不同的,我們可以看看SqlServer的edmx檔案内容(以TB_City表為例)。

而對MySql而言,它的映射關系也和這個類似,主要是SSDL部分的不同,因為具體是和資料庫相關的内容。下面是Mysql的SSDL部分的内容,從下面XML内容可以看到,裡面的資料庫字段類型有所不同。

從以上的對比,我們可以考慮,以一個檔案為藍本,然後在代碼生成工具裡面,根據不同的資料類型,映射成不同的XML檔案,進而生成不同的EDMX檔案即可,實體類和資料通路上下文的類,可以是通用的,這個一點也不影響概念模型的XML内容了,所有部分變化的就是SSDL資料存儲部分的映射XML内容。

為了測試驗證,我增加了Mysql、Oracle共三個的EDMX檔案,并且通過不同的配置來實作不同資料庫的通路調用。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

我們知道,資料上下文的類建構的時候,好像預設是指向具體的配置連接配接的,如下代碼所示(注意紅色部分)。

如果我們需要配置而不是通過代碼寫死方式,那麼是否可以呢?否則寫死的方式,一次隻能是指定一個特定的資料庫,也就是沒有多資料庫的配置的靈活性了。

找了很久,發現真的還是有這樣人提出這樣的問題,根據他們的解決思路,修改代碼如下所示,進而實作了配置的動态性。

我通過在配置檔案裡面,指定ComponentDbType配置項指向那個連接配接字元串就可以了。

OK,這樣就很好解決了,支援多資料庫的問題了。

我們在整個業務部分的項目裡面,把一些通用的内容可以抽取到一個Common目錄層(如BaseBLL/BaseDAL等類或接口),這樣我們在BLL、DAL、IDAL、Entity目錄層,就隻剩下一些和具體表相關的對象或者接口了,這樣的結構我們可能看起來會清晰一些,具體如下所示。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

但是這樣雖然比原先清晰了一些,不過我們如果對基類接口進行調整的話,每個項目都可能導緻不一樣了,我想把它們這些通用的基類内容抽取到一個獨立的公用子產品裡面(暫定為WHC.Framework.EF項目),這樣我在所有項目裡面引用他就可以了,這個做法和我在Enterprise Library架構的做法一緻,這樣可以減少每個項目都維護公用的部分内容,提高代碼的重用性。

基于這個原則,我們重新設計了項目的分層關系,如下所示。

Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)
Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)

這樣我們既可以減少主體項目的類數量,也可以重用公用子產品的基類内容,達到更好的維護、使用的統一化處理。

這個系列文章索引如下:

<a href="http://www.cnblogs.com/wuhuacong/p/4336248.html">Entity Framework 實體架構的形成之旅--基于泛型的倉儲模式的實體架構(1)</a>

<a href="http://www.cnblogs.com/wuhuacong/p/4338564.html">Entity Framework 實體架構的形成之旅--基類接口的統一和異步操作的實作(3)</a>

<a href="http://www.cnblogs.com/wuhuacong/p/4338982.html" target="_blank">Entity Framework 實體架構的形成之旅--實體資料模型 (EDM)的處理(4)</a>