Linq-to-Sql:递归获取孩子

Posted

技术标签:

【中文标题】Linq-to-Sql:递归获取孩子【英文标题】:Linq-to-Sql: recursively get children 【发布时间】:2010-10-06 19:58:51 【问题描述】:

我有一个 CommentID 和 ParentCommentID 的 Comment 表。我正在尝试获取评论的所有子项的列表。这是我目前所拥有的,我还没有测试过。

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 个问题:

    有什么明显的方法可以改善这一点吗? (除此之外,还可以使用 CTE 在 sql 中创建视图。) 为什么我不能将IEnumerable &lt;Comment&gt; 提供给 IEnumerable &lt;Comment&gt;,只有 Comment 本身? 在这种情况下是否可以使用 SelectMany?

【问题讨论】:

这是 Linq to SQL 还是 Linq to Entities? 【参考方案1】:

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

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


Re 2 - 你只能yield 枚举中指定的类型(T in IEnumerable&lt;T&gt; / IEnumerator&lt;T&gt;)。

你可以 yieldIEnumerable&lt;Comment&gt; 如果方法返回 IEnumerable&lt;IEnumerable&lt;Comment&gt;&gt; - 这有意义吗?

改进:

可能是一个使用 CTE 递归方法的 udf(以保持可组合性,而不是存储过程) 使用using,因为DataContextIDisposable...

所以:

using(var db = new MyDataContext() )  /* existing code */ 
LoadWith 值得一试,但我不确定我是否有希望...... 搜索的 id 列表作为一个字段是有风险的 - 我想你没问题,只要你不调用它两次......就个人而言,我会在私有支持方法上使用参数......(即在递归调用之间传递列表,但不在公共 API 上)

【讨论】:

是的,这很有意义,我只是不知道为什么他们不会让你返回一个类型的 ienumerable 或自己的类型 您可以返回类型的 IEnumerable。你可以yield return一个T。 对,我完全理解,但我认为你应该能够做到 如果它只是存在的通用(类型化)版本,我希望它可以......问题是非通用版本会非常模棱两可......你可以@987654333 @任何对象,所以它不知道它是代表一个项目还是一个序列。就个人而言,我很高兴现在的简单方式。

以上是关于Linq-to-Sql:递归获取孩子的主要内容,如果未能解决你的问题,请参考以下文章

中继:获取递归数据返回 null

跳过孩子到父母的获取 - JPA

通过DOM递归搜索去掉innerText

Angular 2:孩子的递归模板

递归二:求老鼠生孩子问题

如何使用递归遍历大纲中的所有孩子?