2009-02-11 74 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