Entity Framework 4 in Action读书笔记——第一章:数据访问重载:Entity Framework(2)...
上一篇講解了通用數據容器,這一篇使用類來組織數據。
類是面向對象編程語言的基礎。使用類,你不需要知道具體的存儲機制,數據源可以是數據庫,Web服務,XML文件等。類提供了很多優勢,尤其是在企業應用中。
1.強類型 2.編譯時檢查 3.易于開發 4.存儲無關
使用類展示數據
我們重新從零開始。你的客戶想要在表格中展示所有的訂單,第一步就是要新建一個Order類容納訂單數據,如下圖所示:
第二步再新建一個類,這個類包含一個從數據庫中讀取數據的方法,并將數據轉換成對象。這個容器類通常放在一個單獨的程序集里,就是所謂數據層。方法代碼如下:
訂單的集合看到這段代碼,很多人的第一反應是,怎么這么多代碼啊?不過沒關系,當事情變得復雜的時候,類就會給我們提供更多的幫助了。
從單個類到對象模型
你已經看到怎樣創建一個單獨的類以及用數據庫中的數據初始化它。但是它真正強大的地方是創建多個類并將它們彼此聯系起來。在數據庫中,Order和OrderDetail之間的關系被描述為Order表中OrderId列和OrderTable中OrderId列的外鍵約束。從數據庫設計的角度,這是正確的方法。但是在面向對象的世界中,這是行不通的。我們創建一個OrderDetail類并給它一個OrderId屬性這是沒有意義的。最好的解決方案就是運用類的獨特性:類的屬性類型可以是用戶自定義的類。也就是說,在Order類中可以引用OrderDetail對象的集合,OrderDetail可以引用Order對象。當創建了這些關系,也就開始創建對象模型了。
關系和對象的不同
了解面向對象和關系的區別很重要,因為它影響著對象模型或者領域模型和數據庫的設計。
下面就從幾個方面講述它們的不匹配。
1、數據類型(datatype)
(1).當往數據庫表中添加一列時,必須確定它的類型?,F代數據庫支持的類型有char, varchar, int, decimal, date等等。但是涉及到類就同了,數據庫中的int和bigint類型可以跟.NET中的Int32和Int64類型匹配,但是數據庫其他類型就沒有跟.NET中類型有確切的匹配了。
(2).在數據庫中可以設置約束條件,比如說給nvarchar類型的數據設置一個最大長度。但是在.NET中沒有nvarchar類型,與此類型相近的就是String類型,如果想設置最大長度只能在屬性中或者方法中設定然后再存儲到數據庫中。
(3).數據庫可以接受二進制數據,但是二進制列不知道這些數據代表什么,可能是一個文本文檔、PDF文件或者圖片。在.NET中可以用Object表示這一列,但是沒有意義,因為你明確的知道在二進制列中存儲的是什么類型的數據。如果存儲的是一個文件,可以用Stream屬性,如果是圖片,那么Images類型是你最佳選擇。
(4).在SQL Server2005中有DateTime和Small-DateTime,SQL Server2008中新增了Date 和 Time兩個類型。如你所想,第一個只存儲日期,第二個只存儲時間。在.NET中只有一個DateTime類來表示日期和時間。
2、關聯(association)
談到關聯,最大的不匹配就是關系世界和對象世界中的關系是怎樣維持的。
(1).一對一關系
如果往Order表中加入其他列,這起初看似是一個小的改動,不會有太大危險,但是事實并非如此,因為很多程序都要用到這個表。替代方法是新建一個表,用OrderId作為主鍵,在這個表中加入新增的列。數據庫中這是一個合理的權衡辦法,如果在對象模型中也這么做,那就沒有意義了。最好的方法就是在Order類中添加一個屬性。如下圖所示:
(2).一對多關系
在數據庫中表示“多”一方的表包含父表中的主鍵。例如,在OrderDetail表中包含一個連接到Order的OrderId列,數據庫術語稱為外鍵。從本質上講,數據庫表的關聯既是單一的又是雙向的。單一的是指只需在OrderDetail一方定義關系,在Order表上不需定義任何東西。雙向是指即使你只修改一方,也會影響到另一方。這是可能的,因為SQL允許你在數據表間執行聯合查詢。
在面向對象世界中,不存在這種機制,因為每樣東西都是明確聲明的。OrderDetail類通過Order屬性到Order的引用,這一點有點像數據庫。實際的不同你也必須修改Order類,添加一個包含OrderDetail對象集合的OrderDetails屬性。這種關系如下圖所示:
(3).多對多關系
多對多關系中,表與表之間的關系沒有主次之分。例如你有Product和Supplier表,你不能簡單的在一個表上創建外鍵表示它們的關系。Product和Supplier表只包含它們自己的數據,這樣一來,兩個表不能直接相連,需要依靠第三個表。
在對象模型中的做法是創建Product和Supplier兩個類。在Product類中添加一個包含Supplier對象集合的Suppliers屬性,同樣,在Supplier類中添加一個包含Product對象集合的Products屬性。如圖所示:
3、顆粒度(granularity)
granularity在這里不知道怎么翻譯比較合適,暫且翻譯成顆粒度吧。顆粒度問題指的是類的個數和數據庫中表的個數不一致。一對一關系中,有兩個表Order和Order2,但是只有一個Order類。還是讓我們看例子吧。
在Order表中有一個送貨地址,被分成了4列:address,city,zip code和country。如果你還要處理其他地址,比如賬單地址,你還要在Order表中添加4列。如圖所示:
在Order類中已經送貨地址的四個屬性,所以再添加四個也不會有問題,盡管它工作的很順利,這些屬性會使類變得越來越大,越來越難懂。更重要的是,customers和suppliers表中有地址,或者其他還有地址。類可以重用,創建一個AddressInfo類,然后重用它不是更好嗎?下面是重構完的代碼:
AddressInfo類和Order類4、繼承(inheritance)
繼承不匹配指的是在數據庫中實現繼承是不可能的。我們添加一個Customer類來完善對象模型,然后讓Customer和Supplier類都繼承自Company。在關系型數據庫中你不能簡單的聲明Customer表繼承自另一個表。你可以創建一個包含Customer和Supplier數據的表或者是單獨創建。不管選擇哪種方式,在數據庫和對象模型都存在不匹配的問題。
在對象模型中,有一個Product類。一個商店各種各樣的產品,如鞋子,襯衫,高爾夫設備,有用設備等等。這些東西都有一些共有的屬性,如價格和顏色等。即使在這樣一個例子中,繼承也會對你有所幫助。現在創建一個Product類,然后為每一個具體的產品創建類。但是當你設計OrderDetail類的時候問題出現了,在OrderDetail類中,需要一個屬性指定是哪個產品的訂單詳細信息。即使在運行時,這個屬性的類型都是Product,具體對象的實例可能是鞋子,襯衫或者任何繼承自Product類型的產品。如圖所示:
這種類型的結構稱為多態,在數據庫中是不可能表示的。
5、標識(identity)
數據庫表中標識一行的是主鍵,因此你為一個表選擇主鍵時一定要注意。有時候你可能想使用自然鍵(natural key),比如產品的代碼,但是這種選擇有可能帶來麻煩。假如你要修改產品的代碼,因為你輸錯了。但是產品代碼在OrderDetail表中是外鍵,所以你必須更新OrderDetail表中的產品代碼。問題是你不能更新OrderDetail表中的產品代碼,因為如果你修改的值在Product表中不存在就會出現錯誤。另一方面,你不能修改Product表中的值,因為違反了外鍵約束。
這看起來是最惱人的問題了,但是還有一個原因要避免使用自然鍵。產品代碼可能是比較長的字符串,但是幾乎所有的數據庫都為存儲和搜索整數值做了優化,所以最有效的主鍵是代理鍵(surrogate key)。代理鍵的使用可以允許你修改其他任何列的值而不用擔心影響到其他表。
到目前為止,我們已經說明了一個對象就是表中一行的面向對象表示,主鍵屬性將對象和行聯系起來。問題是,如果比較兩個相同類型的不同對象,即時它們包含了相同的數據也證明是不相同的。為什么包含相同數據的對象是不同的呢?因為默認情況下指向表示數據庫表中同一行數據的不同對象的兩個變量是不同的。如果兩個變量指向相同的實例,那么它們是相等的,這被稱之為“引用相等”。如果有一個方法可以改變這種默認行為,肯定是更可取的。如果兩個不同的對象包含相同的數據,那么它們比較的結果應該返回True。在.NET中,可以重寫Equals和GetHashCode方法到達同等的效果。
寫在最后的話
在前面,我們看到了關系世界和對象世界之間存在這么多的不同,下一篇將就這些不同給出解決方案。
轉載于:https://www.cnblogs.com/nianming/archive/2011/08/12/2136508.html
總結
以上是生活随笔為你收集整理的Entity Framework 4 in Action读书笔记——第一章:数据访问重载:Entity Framework(2)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: T420s成功加装固态硬盘(SSD)
- 下一篇: 智联招聘让人非常反感的一个功能:自动委托