2009-12-12 51 views
0

我有一個linq-to-sql數據層,裏面有兩個表。 「父母」和「孩子」。孩子和父母之間有一種關係(所以父母有很多孩子等等),父母也可以有很多父母(當孩子長大併成爲父母的時候)。在Linq-To-Sql中有效選擇一棵樹

我想顯示給用戶這個層次結構,但我不知道如何有效地做到這一點。

低效的做法是要做到:

foreach(Parent in db.Parents) 
{ 
    output(Parent.Parents) 
    output(Parent.Children) 
} 

但是,這兩次生成一個數據庫往返中環(伊克!)每次迭代,如果它是一個大家庭,這將是真的很貴。

有沒有更好的方法? (上帝,我希望如此!)

回答

1

我會建議急於加載你想傳遞給用戶界面的整個集合。如果生成父 - >父集合的方法是遞歸的(看起來可能是這樣),那麼使用L2S代碼以遞歸方式選擇項目。通過這種方式在UI中迭代結果的最終集合不會以低效的方式觸發SQL命令。

例子:
我不知道這是否是最好的/最短/清潔要做到這一點的方式,但希望你會明白我的意思。 static功能因其控制檯應用程序。

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (ParentDTO p in GetParents().ToList()) 
     { 
      if (p.Parent == null) 
       Console.WriteLine(String.Format("{0} ({1})", 
        p.Name, p.ID.ToString())); 
      else 
       Console.WriteLine(String.Format("{0} ({1}){2}", 
        p.Name, p.ID.ToString(), "\r\n\t-" + p.Parent.Name)); 
     } 

     Console.ReadKey(); 
    } 

    private static IQueryable<ParentDTO> GetParents() 
    { 
     var db = new DataClasses1DataContext(); 
     db.Log = new DebuggerWriter(); 

     return from p in db.Parents 
       let parentParent = GetParentOfParent(p.ParentID) 
       select new ParentDTO 
       { 
        ID = p.ID, 
        Name = p.Name, 
        Parent = parentParent 
       }; 
    } 

    private static ParentDTO GetParentOfParent(int? childParentID) 
    { 
     if (childParentID.HasValue) 
      return GetParents().Single(p => p.ID == childParentID); 
     else 
      return null; 
    } 
} 

表數據:

ID PARENTID名稱
1 NULL比爾
2 8瑪麗
3 1加里
4 1米拉
5 NULL蘇
6 NULL佛瑞德
7 NULL Marg
8 7 Hillary

輸出:

比爾(1)
瑪麗(2)
-Hillary
加里(3)
- 比爾
米拉(4)
- 比爾
Sue(5)
Fred(6)
Mar克(7)
希拉里(8)
-Marg

(縮進/連字符名稱相應的父母)

這是從L2S直流Log輸出調試器:

SELECT [t0]。[ID],[t0]。[ParentID],[t0]。[Name]
FROM [dbo]。[Parent] AS [t0]
WHERE([t0]。[ID])= @ p0
- @ p0:Input Int(Size = 0; Prec = 0;規模= 0)[8]
- 上下文:sqlProvider的(SQL2005)型號:AttributedMetaModel體形:3.5.30729.1

SELECT [T0] [ID],[T 0] [PARENTID],[T0]。 [名稱]
FROM [DBO] [父] AS [T0]
WHERE([T 0] [ID])= @ P0
- @ P0:輸入INT(大小= 0; PREC = 0; Scale = 0)[7]
- 上下文:SqlProvider(Sql2005)模型:Attri butedMetaModel建設:3.5.30729.1

SELECT [T 0] [ID],[T 0] [PARENTID],[T 0] [名]
FROM [DBO] [家長] AS [T 0]
。。 WHERE([t0]。[ID])= @ p0
- @ p0:Input Int(Size = 0; Prec = 0;規模= 0)[1]
- 上下文:sqlProvider的(SQL2005)型號:AttributedMetaModel體形:3.5.30729.1

SELECT [T0] [ID],[T 0] [PARENTID],[T0]。 [名稱]
FROM [DBO] [父] AS [T0]
WHERE([T 0] [ID])= @ P0
- @ P0:輸入INT(大小= 0; PREC = 0;規模= 0)[1]
- 上下文:sqlProvider的(SQL2005)型號:AttributedMetaModel體形:3.5.30729.1

SELECT [T0] [ID],[T 0] [PARENTID],[T0]。 [名稱]
FROM [dbo]。[Paren t] AS [t0]
WHERE([t0]。[ID])= @ p0
- @ p0:Input Int(Size = 0; Prec = 0;規模= 0)[7]
- 上下文:sqlProvider的(SQL2005)型號:AttributedMetaModel體形:3.5.30729.1

..所有其燒製一氣呵成在.ToList();線(如預期)。

我希望這是有用的。

+0

這聽起來不錯,謝謝...什麼l2s代碼可用於遞歸方式選擇項目? – Paul 2009-12-12 08:49:02