2011-03-14 187 views
2

我有一個名爲Category的對象,它具有Id,Name和OwnerId。然後我嵌套這些來創建子類別。如果一個類別擁有一個所有者ID,它就是一個子類別。子類別的數量是無限的,但每個項目只能有1個父項目。夠簡單。Linq to SQL嵌套對象

我的問題是,我需要裝後訪問一個子類別。我如何使用Linq獲得擁有類別。我知道主人身份證,但我不知道主人可能有多少深度。

基本上,我正在尋找一種方式來獲得類別或子類別其中ID = = X,但這種能夠生活在一個子類6級以上深。

我試圖避免在每個子類的每個子類循環....

回答

0

在MS SQL 2005和最多可以創建遞歸查詢。但是,在LINQ to SQL中,你運氣不佳。如果不重構數據庫中的數據,則無法在單個數據庫調用中遍歷樹。

但是...有1個解決方法我能想到的。如果能夠將單個樹(或樹的一部分)的所有Category元素分組在一起,則可以在單個語句中預加載完整樹的該部分。之後,您將能夠遍歷該樹的該部分,而不會觸發對數據庫的新調用。它看起來像這樣:

// Load the category that will be used as starting point. 
var subCategory = db.Categories.Single(c => c.Id == 56); 

// Performance: Load the complete group in one go. 
var categories = (
    from category in db.Categories 
    where category.GroupId == subCategory.GroupId 
    select category) 
    .ToArray(); 

// Traverse the tree and get the top-most parent (if any). 
var parent = subCategory.GetParents().LastOrDefault(); 

// Extension method to get the parents. 
public static IEnumerable<Category> GetParents(
    this Category category) 
{ 
    while (category.Parent != null) 
    { 
     // NOTE: cat.Parent will not cause a database call 
     // when the Parent is already loaded by L2S. 
     yield return cat.Parent; 
     category = category.Parent; 
    } 
} 

這當然只有在你能夠確定元素爲一個組時纔有用。這個解決方案是否會更快取決於組的大小。當您加載(並且不使用)的對象組非常大時,它實際上會減慢應用程序的速度。

1

有存儲/檢索樹層次結構爲this fogbugz博客中解釋另一種方式:

原來有這個問題,通過 喬·塞科解釋一個很酷的 解決方案。而不是嘗試 維護一堆父/子 關係遍佈您的數據庫 - 這將需要遞歸SQL查詢來查找所有節點的後裔 - 我們標記每個 案例與「左」和「右邊「值 通過遍歷樹 深度優先計算,並隨着我們走。一個 節點的「左」值被設置時,它 穿越過程中第一次看到,而且走路時 備份樹從節點離開 「正確」的值設置。 一張圖片可能更有意義:

enter image description here

嵌套組SQL模式讓我們添加 情況下層次結構在不犧牲性能的 。

這有什麼用?現在我們只是要求 所有例2和9之間的「左」值 找到所有B的 後代在一個快速,索引 查詢。的G祖先是由 發現要求與「左」小於 6(G自己的「左」)和「右」大 比6.適用於所有的數據庫節點。查詢大 層次

Here's another post進入更詳細特別是當 - 大大提高了性能。它使用Sqlphp編寫,但我認爲你可以獲得它的要點,並很容易在Linq中轉換爲Sql。