English 中文(简体)
Linq-to-Sql:递归获取子级
原标题:
  • 时间:2009-02-11 04:27:41
  •  标签:

我有一张评论表,其中包含评论ID和父评论ID。我试图获取所有评论的子评论列表。这是我目前拥有的,我还没有测试过它。

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;
        }
    }
}

两个问题:

  1. Is there any obvious way to improve this? (Besides maybe creating a view in sql with a CTE.)
  2. How come I can t yield a IEnumerable <Comment> to an IEnumerable <Comment>, only Comment itself?
  3. Is there anyway to use SelectMany in this situation?
最佳回答

我可能会使用UDF / CTE或(对于非常深的结构)手动执行相同操作的存储过程。

请注意,如果您可以更改架构,您可以将这种递归结构预索引到索引/范围树中,从而使您可以执行单个BETWEEN查询,但树的维护成本很高(即查询变得便宜,但插入/更新/删除变得昂贵,或者您需要延迟计划任务)。


Re 2 - 您只能 yield 枚举中指定的类型(IEnumerable<T> / IEnumerator<T> 中的 T)。

如果该方法返回IEnumerable>,则可以yield一个IEnumerable。这有道理吗?

改进:

  • perhaps a udf (to keep composability, rather than a stored procedure) that uses the CTE recursion approach
  • use using, since DataContext is IDisposable...

这样:

using(var db = new MyDataContext() ) { /* existing code */ }
  • LoadWith is worth a try, but I m not sure I d be hopeful...
  • the list of searched ids is risky as a field - I guess you re OK as long as you don t call it twice... personally, I d use an argument on a private backing method... (i.e. pass the list between recursive calls, but not on the public API)
问题回答

暂无回答




相关问题
热门标签