【问题标题】:Linq to recurse through a hierarchyLinq 通过层次结构递归
【发布时间】:2013-04-23 07:27:50
【问题描述】:

我有一个层次结构的数据结构如下。

表 1

id | Groupname | parentId

表 2

id | nodeName | parentId

表1的parentId指的是表1的id,表2的parentId也指的是表1的id。

从表1中的任意一个ID开始,我需要打印出所有节点,然后遍历所有子组的子节点。

到目前为止我有这个

int id = 1; // replace with argument

repository.Nodes.Where(n => n.ParentId == Id).ToList().ForEach(d =>
{
  result.NodeList.Add(GetNodeDetails(n.Id));
});

谁能帮我以高效的 linq 方式完成这个循环?

【问题讨论】:

  • 所以你想扁平化层次结构,对吗?
  • 如何获取节点的子节点?有导航属性吗?
  • 是的,我想展平,是的,有导航属性。谢谢。
  • repository.Nodes 已经是所有节点的扁平化列表。
  • @dtb:他不想要所有节点。他只想要Id 的子集。

标签: c# linq linq-to-entities


【解决方案1】:

如果我理解正确,您希望扁平化层次结构,即最终结果应该是一个扁平列表,其中包含所有层次结构级别的所有子级。

实现这一点的最简单方法是通过递归:

private IEnumerable<Node> GetSelfAndChildren(Node node)
{
    yield return GetNodeDetails(n.Id);
    foreach(var c in n.Children.SelectMany(GetSelfAndChildren)
        yield return c;
};


var result = repository.Nodes.Where(n => n.ParentId == Id)
                       .AsEnumerable()
                       .SelectMany(GetSelfAndChildren)
                       .ToList();

这使用递归方法来获取子列表。

这种方法有可能会出现 N+1 问题。根据配置,Children 的每次访问都会导致到数据库的往返。
如果 N+1 问题正在发生并导致 - 很好 - 问题,另一种方法是首先从数据库中获取 所有 节点,然后执行Breadth-first search

【讨论】:

  • @roliu:我不确定我明白你在问什么。我的代码显然有一个循环。但是你不能用 only 一个循环来实现它 - 至少不容易。
  • @DavidB:请看更新,我把 lambda 改成了一个方法。
  • @roliu:我改写了那部分。我想可以使用 BFS,你是对的。我在图论方面不是特别强,所以我只是没有考虑过。感谢您提及。
  • @DavidB:你说代码超出了你的范围。你有什么特别需要解释的吗?
  • @DavidB:好的。是的,看看产量。这是支持 LINQ to Objects 及其延迟执行的关键字。
猜你喜欢
  • 1970-01-01
  • 2014-01-25
  • 2013-11-22
  • 2017-02-04
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 2023-03-24
  • 2015-11-23
相关资源
最近更新 更多