【转】【翻译】实体框架中的POCO支持 - 第二部分 - 复杂类型,延迟装载和显式装载...
【原文地址】POCO in the Entity Framework : Part 2 – Complex Types, Deferred Loading and Explicit Loading 
【原文發表日期】 28 May 09 09:03 AM 
在上星期的貼子《POCO Experience in Entity Framework》 (實體框架中的POCO體驗)中,我討論了Entity Framework 4.0中POCO支持的基本。在這個貼子里,我將討論與POCO相關的另外幾個方面。
復雜類型(Complex Types)
POCO中的復雜類型支持跟常規的基于EntityObject的實體中的復雜類型支持一樣。你要做的就是將它們聲明為POCO類,然后在你的POCO實體中使用和聲明基于它們的屬性。
作為例子,這里是一個InventoryDetail復雜類型,代表我的Product實體的一個部分:
public class {public UnitsInStock { ; ; }
public UnitsOnOrder { ; ; }
public ReorderLevel { ; ; }
}
把我的Product類修改成包含一個這個類型的屬性,用來組合幾個有關庫存細節的字段:
public class {public int ProductID { ; ; }
public string ProductName { ; ; }
public int SupplierID { ; ; }
public string QuantityPerUnit { ; ; }
public decimal UnitPrice { ; ; }
public InventoryDetail { ; ; }
public bool Discontinued { ; ; }
public Category { ; ; }
}
然后你可以做你以前對復雜類型所能做的一切,這是一個查詢的例子:
outOfStockProducts = c in context.Productswhere c.InventoryDetail.UnitsInStock == 0
c;
?
你可以看到,POCO中的復雜類型支持用起來非常直截了當。但在POCO中使用復雜類型支持時,你需要記住幾件事情:
既然在討論復雜類型,我想我要提一下另外一件事,你知道Visual Studio 2010中的實體框架設計器支持復雜類型的聲明么?
在Visual Studio 2008中,你只能手工將復雜類型的聲明加到CSDL中去,但隨著Visual Studio 2010中的設計器中對復雜類型支持的推出,這一切都成了歷史。
更酷的是,因為Visual Studio 2010支持多定向(Multi-Targeting),你可以在開發針對.NET Framework 3.5,使用了Entity Framework 3.5的應用中也使用這個功能!
延遲/懶式裝載
在我2個星期前發表的《延遲裝載初覽》一文中,我提到了實體框架現在支持延遲裝載了。默認的、代碼生成的基于EntityObject的實體類型將提供延遲裝載,自然毫不奇怪。如果你想知道POCO對象中是否也支持延遲裝載,那么我想,你會很高興地知道,你在POCO中也能得到延遲裝載支持。
為在POCO實體中使用延遲裝載支持,你需要做2件事情:
例如,這里是更新過的Category實體類的部分代碼,我將其改成支持延遲裝載了:
public class{
public int CategoryID { ; ; }
public string CategoryName { ; ; }
public string Description { ; ; }
public byte[] Picture { ; ; }
public virtual <> Products { ; ; }
...
???? 2.?? 在上下文中啟用延遲裝載選項: 
?
這就行了,你現在就將得到POCO類型的自動延遲裝載,而不用做任何其他什么事情。
那么這玩意到底是怎么工作的,底層是怎么進行的?
這玩意能工作的原因是因為,在我將集合類型的屬性標記為virtual后,這允許實體框架在運行時為我的POCO類型提供一個代理(proxy) 實例,正是這個代理實現了自動的延遲裝載。該代理實例是基于一個繼承自我的POCO實體類的類型,所以你提供的所有功能都被保留下來了。從開發人員的角度來看,即使延遲裝載或許是個需求,這也允許你編寫透明持久性的代碼。
如果你在調試器中檢查實際的實例時,你會看到該實例的底層類型與我原先聲明的類型是不同的:
雖然實體框架盡力以最小的摩擦提供自動的延遲裝載,但在處理你想要添加或附加手工生成的實例時,或者當你序列化/發序列化實例時,這是你需要知道的事情。
為POCO實體手工生成代理實例
為了允許可以添加或附加的代理實例的生成,你可以使用ObjectContext上的CreateObject工廠方法來生成實體實例:
category = context.CreateObject<>();?
要把這個記住,在生成你想要用于實體框架的實例時,要使用CreateObject。
用“變動跟蹤代理(Change Tracking Proxies)”來提供更有效的變動跟蹤
到目前為止,我們討論過的標準POCO實體都依賴于基于快照(snapshot)的變動跟蹤,即,實體框架會保管實體變動之前的值和關系的快照,這樣,在保存(Save)時,可以與當前的值做比較。但這個比較的花銷是相當大的,如果跟基于EntityObject的實體的變動跟蹤的方式相比的話。
還有另外一種類型的代理,它允許你在使用POCO實體時得到比較好的變動跟蹤性能。
如果你熟悉IPOCO接口,你知道IEntityWithChangeTracker是要求你在類中實現、來向實體框架提供變動通知的接口之一。
變動跟蹤代理從你的POCO實體類繼承而來,在運行時給你提供這個功能,而不要求你自己實現IPOCO接口。
從許多方面講,用這種方式的話,你是魚與熊掌都兼得了:你得到了POCO類的透明持久性,在變動跟蹤方面你也得到了EntityObject / IPOCO 的性能。
為了得到變動跟蹤代理,基本的規則是,你的類必須是公開的,非抽象的或者非密封的(non-sealed)。你的類對所有要持久的屬性都必須實現公開的virtual getters/setters。最后,你必須將基于集合的關系導航屬性嚴格聲明為ICollection<T>。它們不能是具體的實現或者繼承自ICollection<T>的另外的接口(與延遲裝載代理有所不同)。
這里是我的Product POCO類的例子,它將在運行時給我提供更有效的基于代理的變動跟蹤:
public class {public virtual int ProductID { ; ; }
public virtual string ProductName { ; ; }
public virtual int SupplierID { ; ; }
public virtual string QuantityPerUnit { ; ; }
public virtual decimal UnitPrice { ; ; }
public virtual InventoryDetail { ; ; }
public virtual bool Discontinued { ; ; }
public virtual Category { ; ; }
}
再說一遍,要記住,如果你要將實體加到或附加到上下文的話,你必須使用CreateObject來生成代理實例。但不依賴代理的純粹的POCO實體和基于代理的實體可以共處。你只有在涉及基于代理的實體時才需使用CreateObject。
如果我想在同個POCO類型中同時啟用延遲裝載和更好的變動跟蹤,該怎么辦?
這兩個東西不是互相排斥的,你不必在延遲裝載代理和變動跟蹤代理間做選擇。如果你想要延遲裝載,以及有效的變動跟蹤,你只要按照變動跟蹤代理的規則辦,以及啟用延遲裝載選項。變動跟蹤代理會給你提供延遲裝載,如果延遲裝載選項是啟用了的話。
顯式裝載
這個延遲裝載的功能確實很棒,但你們中很多人大概想要完全控制你是如何裝載相關實體的吧。你甚至會選擇走純粹的POCO之路,而不訴諸于任何自動代理生成能給你提供的功能。
這是完全可以接受的,(在很多情形下也許是更好的方法),你可以使用顯式關系裝載,對你是如何在數據庫中查詢數據的做完全的控制。
在POCO中做顯式裝載,有2個選項:
一個是使用 ObjectContext.LoadProperty ,設置你想要裝載的導航屬性的名稱:
context.LoadProperty(beveragesCategory, );這是可行的,但你可以看出來,這并不類型安全(type safe)。如果我沒有正確的導航屬性的名稱的話,我會得到一個運行時異常。
你們中的一些人大概更喜歡這個:
context.LoadProperty(beveragesCategory, c => c.Products);我可以使用lambda表達式來指定我想要顯式裝載的屬性,這提供了更好的類型安全。
上面是我計劃在這第二個貼子里討論的所有的內容了。但以后還會有更多內容,在這個系列的最后一篇里,我們將討論在處理純POCO(非代理化的)實例以及在你的對象圖和對象狀態管理器(Object State Manager)間保持一致時需要知道的幾件事情。我們也會討論你也許想要知道的SaveChanges方法的多個變種。
與此同時,請看一下我更新過的樣例代碼,其中包括了我們在本貼里討論過的一些東西。
Faisal Mohamood 
Entity Framework的Program Manager
推薦文章
- 博客堂源代碼發布已經發布于Codeplex,邀請您來捉臭蟲
- 面向對象設計講義
- 如何判斷當前瀏覽器是否是IE8?
- ten years of msn
- 硅脂
- MVC模式結合Mediator模式的運用
- 有點郁悶:MSDN文檔中MidpointRounding.AwayFromZero的翻譯錯誤
- CodeFx 6月14日更新:14個新示例代碼
- 作用域
- Expression Web 3
- [Excel Services]連接外部數據庫,刷新數據的時候遇到“Data Refresh Failed ”的解決方法
轉載于:https://www.cnblogs.com/lfzx_1227/archive/2009/05/29/1550629.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【转】【翻译】实体框架中的POCO支持 - 第二部分 - 复杂类型,延迟装载和显式装载...的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: flash怎么制作一个可爱的卡通猴子
- 下一篇: 什么是依赖注入?(听来的一个笑话)
