2012-09-02 47 views
2

我在我的模型設計中有一個非常深的關係樹,也就是根實體包含一個包含更多其他實體集合的實體集合,這些集合包含更多的集合,並且在...上開發一個業務層,其他開發人員必須使用來執行操作,包括獲取/保存數據。你如何處理實體框架中的深層關係樹?

然後,我正在考慮應對這種情況的最佳策略是什麼。我不能在檢索實體時允許EF解析所有的依賴樹,因爲它會以很多無用的JOIN結束(無用,因爲我可能不需要下一級的數據)。

  • 如果我禁用延遲加載執行預先加載對於需要什麼,它工作正常,但如果其他開發人員調用child.Parent.Id而不是child.ParentId嘗試做一些新的東西(如新的要求或功能在開始時不考慮),如果不包括該依賴關係,它將得到一個NullReferenceException,這是不好的......但這將是一個「快速錯誤」,並且可以立即修復。

  • 如果我啓用延遲加載,訪問的child.Parent.Id代替child.ParentId在一個獨立的查詢中的每個被訪問時將結束到數據庫。它不會失敗,但它更糟,因爲沒有錯誤,只有性能下降,並且應該檢查所有代碼。

我對這兩種解決方案都不滿意。

  • 我不高興有實體包含null或空集合,但實際上,它不是真實的。

  • 我不滿意讓EF在任何時候對數據庫執行任意查詢。我想盡可能在​​一次拍攝中獲得所有信息。

所以,我想出了涉及禁用延遲加載執行預先加載幾種可能的解決方案,但不知道哪個好:

  • 我能創造一個EntityBase類,它包含表中沒有集合的數據,所以它們不能被訪問。而包含關係的具體實現,問題是你沒有太大的靈活性,因爲C#不允許多重繼承。

  • 我可以創建接口來「掩蓋」隱藏在該方法調用時不可用的屬性的對象。例如,如果我擁有一個User.Roles屬性,爲了向所有用戶顯示一個網格,我不需要解析.Roles屬性,因此我可以創建一個不包含此屬性的接口「IUserData」。

但我不,如果這些額外的工作是值得的,也許快NullReferenceException表示「該屬性尚未加載」就足夠了。

如果該屬性是虛擬的並且它沒有被覆蓋/設置,是否可以拋出特定的異常類型?

你使用什麼方法?

謝謝。

+0

從你使用它的例子看起來你主要走樹底,是嗎? –

+0

不是,它只是一個例子。你爲什麼要問? – vtortola

回答

8

我認爲你是trying to protect the developers需要了解他們在訪問數據時所做的工作以及它可能產生的性能影響 - 這可能會導致一個不必要的複雜的API,其中包含許多輔助類,基類,接口等

如果開發人員使用user.MiddleName.Trim()MiddleNamenull他得到一個NullReferenceException和做錯了什麼,或者沒有檢查null或者沒有確保該MiddleName被設置爲一個值。當他訪問user.Roles並得到NullReferenceException時也是如此:他沒有檢查null,也沒有調用加載用戶的Roles的API的適當方法。

我會說:解釋導航屬性是如何工作的,並且必須明確請求它們,並且如果開發人員不遵守規則,就讓應用程序崩潰。他需要了解錯誤並修復它。

作爲一個幫助你可以做負載相關的數據以某種方式在API明確,例如用類似的方法:

public User GetUser(int userId); 
public User GetUserWithRoles(int userId); 

或者:

public User GetUser(int userId, params Expression<Func<User,object>>[] includes); 

這可能與被稱爲

var userWithoutRoles = layer.GetUser(1); 
var userWithRoles = layer.GetUser(2, u => u.Roles); 

您還可以利用顯式加載而不是延遲加載來強制開發人員在他們要加載導航屬性時調用方法,而不是僅訪問該屬性。

兩個補充說明:

...延遲加載......將在每次訪問時間 一個獨立的查詢到DB結束。

...還沒加載」來完成此操作。如果導航屬性已在同一個上下文中加載,則再次訪問該屬性不會觸發對數據庫的查詢。

我想盡可能在​​一次拍攝中獲得所有信息。

多個查詢不一定會導致性能比具有很多Include s的查詢更糟糕的性能。事實上,複雜的熱切加載can lead to data multiplication on the wire並使實體實現非常耗時並且比多個惰性或顯式加載查詢要慢。 (Here is an example),其中查詢的性能通過將其從單個查詢(Include)更改爲超過1000個查詢(而不是Include)而得到改進,其性能已提高50倍。)Quintessence是:您無法可靠地預測在特定情況下什麼是最佳裝載策略,而無需衡量性能(如果性能在這種情況下很重要)。

+0

這是一個夢幻般的答案。我喜歡那種加載表達式列表的方法。你在「複雜的熱切」問題上提出了一個很好的觀點,我會仔細閱讀這些鏈接。非常感謝。 – vtortola