2009-02-11 154 views
5

我有一個評論表,它有一個CommentID和一個ParentCommentID。我正在嘗試獲得評論的所有孩子的名單。這是我到目前爲止,我還沒有測試過。Linq-to-Sql:遞歸地獲取子女

private List<int> searchedCommentIDs = new List<int>(); 
// searchedCommentIDs is a list of already yielded comments stored 
// so that malformed data does not result in an infinite loop. 
public IEnumerable<Comment> GetReplies(int commentID) { 
    var db = new DataClassesDataContext(); 
    var replies = db.Comments 
     .Where(c => c.ParentCommentID == commentID 
      && !searchedCommentIDs.Contains(commentID)); 
    foreach (Comment reply in replies) { 
     searchedCommentIDs.Add(CommentID); 
     yield return reply; 
     // yield return GetReplies(reply.CommentID)); // type mis-match. 
     foreach (Comment replyReply in GetReplies(reply.CommentID)) { 
      yield return replyReply; 
     } 
    } 
} 

2個問題:

  1. 是否有改善這個任何明顯的方法是什麼? (除了可能用CTE創建一個sql視圖)
  2. 我怎麼能不能讓一個IEnumerable <Comment>到IEnumerable <Comment>,只有Comment本身?
  3. 無論如何在這種情況下使用SelectMany?
+0

這是LINQ到SQL或LINQ到實體? – bendewey 2009-02-11 04:35:37

回答

4

我可能會使用UDF/CTE或(對於非常深的結構)手動執行相同操作的存儲過程。

請注意,如果您可以更改模式,您可以將此類遞歸結構預先索引到索引/範圍樹中,以便您執行單個BETWEEN查詢 - 但樹的維護很昂貴(即查詢變得便宜,但插入/更新/刪除變得昂貴,或者您需要延遲的計劃任務)。


RE 2 - 你只能yield在枚舉中指定的類型(在TIEnumerable<T>/IEnumerator<T>)。

你可以yieldIEnumerable<Comment>如果該方法返回IEnumerable<IEnumerable<Comment>> - 這是否有意義?

改進:

  • 也許UDF(保持組合性,而不是存儲過程)使用CTE的遞歸方法
  • 使用using,因爲DataContextIDisposable ...

so:

using(var db = new MyDataContext()) { /* existing code */ } 
  • LoadWith是值得一試,但我不知道我會希望...
  • 搜索id的列表是危險的作爲字段 - 我猜你只要沒事,你不要不要再說兩遍......我個人會在私人支持方法上使用一個論點......(即通過遞歸調用的列表,但不能在公共API)
+0

是啊,這是絕對意義上我只是不知道爲什麼他們wouldnt讓你要麼返回一個IEnumerable的類型或類型的tiself – Shawn 2009-02-11 04:43:26