天天看點

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

在前陣子,我對實體架構進行了一定的研究,然後把整個學習的過程開了一個系列,以逐漸深入的方式解讀實體架構的相關技術,期間每每碰到一些新的問題需要潛入研究。本文繼續前面的主題介紹,着重從整體性的來總結一下實體架構的一些方面,希望針對這些實際問題,和大家進行學習交流。

我的整個實體架構的學習和研究,是以我的Winform架構順利更新到這個實體架構基礎上為一個階段終結,這個階段事情很多,從開始客運聯網售票的WebAPI平台的開發,到微軟實體架構的深入研究,以及《基于Metronic的Bootstrap開發架構經驗總結》的主題學習和分享等等方面,都混到一起來了,多個主題之間穿插着寫一些随筆,也是希望把自己的學習過程進行記錄總結,不用等到最後全部忘記了。

 在我們搭建整個實體架構的過程中,我們一般都是抽象封裝處理很多基礎的增删改查、分頁等常見的資料處理功能,如下所示。

上面的外鍵統一定義為object類型,因為我們為了主鍵類型通用的考慮。

在實際上表的外鍵類型可能是很多種的,如可能是常見的字元類型,也可能是int類型,也可能是long類型等等。如果我們更新、查找、删除整形類型的記錄的時候,那麼可能機會出現錯誤:

這些錯誤就是主鍵類型不比對導緻的,我們操作這些接口的時候,一定要傳入對應類型給它們,才能正常的處理。

本來想嘗試在内部進行轉換處理為正确的類型的,不過沒有找到很好的解決方案來識别和處理,是以最好的解決方法,就是我們調用這些有object類型主鍵的接口時,傳入正确的類型即可。

又或者是下面的代碼:

在很多時候,我們都會用到遞歸函數的處理,這樣能夠使得我們把整個清單的内容都合理的提取出來,是我們開發常見的知識點之一。

不過一般在處理LINQ的時候,它的遞歸函數的處理和我們普通的做法有一些差異。

例如我們如果要擷取一個樹形機構清單,如果我們指定了一個開始的機構節點ID,我們需要遞歸擷取下面的所有層次的集合的時候,正常的做法如下所示。

這裡面的大概思路就是把符合條件的集合全部弄到DataTable集合裡面,然後再在裡面進行檢索,也就是遞歸擷取裡面的内容。

上面是正常的做法,可以看出代碼量還是太多了,如果使用LINQ,就不需要這樣了,而且也不能這樣處理。

使用實體架構後,主要就是利用LINQ進行一些集合的操作,這些LINQ的操作雖然有點難度,不過學習清楚了,處理起來也是比較友善的。

在資料通路層,處理上面同等的功能,LINQ操作代碼如下所示。

基本上,可以看到就是兩行代碼了,是不是很神奇,它們實作的功能完全一緻。

不過,也不是所有的LINQ遞歸函數都可以做的非常簡化,有些遞歸函數,我們還是需要使用正常的思路進行處理。

不過相對來說,LINQ已經給我們帶來的非常大的便利了。

我們在做一些表的時候,一般情況下都會有日期類型存在,如我們的生日,建立、編輯日期等,一般我們資料庫可能用的是datetime類型,如果這個日期的類型内容在下面這個區間的話:

我們可能就會得到下面的錯誤:

一般之是以會報錯資料類型轉換産生一個超出範圍的值,都是因為資料的大小和範圍超出要轉換的目标的原因。我們先看datetime2和datetime這兩個資料類型的具體差別在哪裡。

這裡值的注意的是datetime2的日期範圍是"0001-01-01 到 9999-12-31"(公元元年 1 月 1 日到公元 9999 年 12 月 31 日)。而datetime的日期範圍是:”1753 年 1 月 1 日到 9999 年 12 月 31 日“。這裡的日期範圍就是造成“從 datetime2 資料類型到 datetime 資料類型的轉換産生一個超出範圍的值”這個錯誤的原因!!!

在c#中,如果實體類的屬性沒有指派,一般都會取預設值,比如int類型的預設值為0,string類型預設值為null, 那DateTime的預設值呢?由于DateTime的預設值為"0001-01-01",是以entity framework在進行資料庫操作的時候,在傳入資料的時會自動将原本是datetime類型的資料字段轉換為datetime2類型(因為0001-01-01這個時間超出了資料庫中datetime的最小日期範圍),然後在進行資料庫操作。問題來了,雖然EF已經把要儲存的資料自動轉為了datetime2類型,但是資料庫中表的字段還是datetime類型!是以将datetime2類型的資料添加到資料庫中datetime類型的字段裡去,就會報錯并提示轉換超出範圍。

解決方法如下所示:

這個問題的解決方法:

C#代碼中 DateTime類型的字段在作為參數傳入到資料庫前記得指派,并且的日期要大于1753年1月1日。

C#代碼中 将原本是DateTime類型的字段修改為DateTime?類型,由于可空類型的預設值都是為null,是以傳入資料庫就可以不用指派,資料庫中的datetime類型也是支援null值的。

修改資料庫中表的字段類型,将datetime類型修改為datetime2類型

例如,我在實體架構裡面,對使用者表的日期類型字段進行初始化,這樣就能保證我存儲資料的時候,預設值是不會有問題的。

有時候,雖然這樣設定了,但是在界面可能給這個日期字段設定了不合理的值,也可能産生問題。那麼我們對于這種情況,判斷一下,如果小于某個值,我們給它一個預設值。

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

在界面調整這塊,我們還是盡可能保持着的Enterprise Library的Winform界面樣式,也就是混合型或者普通Winform的界面效果。不過這裡我們是以混合式架構進行整合測試,是以實體架構的各個方面的調用處理基本上保持一緻。

》。

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

是以我們在界面操作的都是DTO對象類型了,我們在定義的時候,為了避免更多的改動,依舊使用***Info這樣的類名稱作為DTO對象的名稱,***代表表名對象。

在混合式架構的界面表現層,它們的資料對象的處理基本上保持和原來的代碼差不多。

但我們需要在WCF服務層說明他們之間的映射關系,友善進行内部的轉換處理。

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

在實體架構界面層的查詢中,我們也不在使用部分SQL的條件做法了,采用更加安全的基于DTO的LINQ表達式進行封裝,最後傳遞給背景的也就是一個LINQ對象(非傳統方式的實體LINQ,那樣在分布式進行中會出錯)。

如查詢條件的封裝處理如下所示:

而分頁查詢的處理,依舊和原來的風格差不多,隻不過這裡的Where條件為ExpressionNode 對象了,如代碼所示、

最後我們來看看整個實體架構的結構和界面的效果介紹。

界面效果如下所示:

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

代碼結構如下所示:

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結

架構設計的效果圖如下所示:

Entity Framework 實體架構的形成之旅--實體架構的開發的幾個經驗總結