【问题标题】:Recursively get all nodes that match in LINQ递归获取 LINQ 中匹配的所有节点
【发布时间】:2018-07-14 03:52:15
【问题描述】:

有没有办法在 linq 中执行以下操作?

//item properties
//EntityId
//ParentEntityId
//HierarchyLevel

var topItem = myList.Single(x => x.HierarchyLevel == 0);
var level1 = myList.Where(x => x.ParentEntityId == topItem.EntityId);

//can i do the next step in LINQ?
//var level2 =

3 级呢?我是否已经在 SQL 中使用 CTE 完成了此操作,但不确定在 C# 中执行此操作的正确方法。

【问题讨论】:

  • Linq 并不真正适合递归。
  • 是的,您可以使用 linq 进行递归,但要获得答案,您必须发布一个更好的问题。看看这个旧答案stackoverflow.com/a/12243888/932418

标签: c# linq recursion


【解决方案1】:

你有几个选择:

1) 使用上一层的信息查询下一层。所以基本上使用递归,但不是在 LINQ 中一步完成所有事情。

var currLevel = myList.Where(x => x.HierarchyLevel == 0);
while (currLevel.Any())
{
    // Note: Maybe faster if myList was converted to a lookup first
    //       for this part, but this won't be an option if this is
    //       Linq2Sql, EF, etc. unless you pull everything into memory.
    var nextLevel = myList.Where(x => currLevel.Select(c => c.EntityId)
                                               .Contains(x.ParentEntityId));

    // Do something here with additional levels.

    var currLevel = nextLevel;
}

2) 使用类似 LINQ AsHierarchy 的东西,它本质上是一样的,但它以可重用的数据结构呈现:

var root = myList.AsHierarchy(x => x.EntityId, x => x.ParentEntityId)
                 .Single();

var level2 = root.ChildNodes;

var level3 = level2.SelectMany(x => x.ChildNodes);

3) 将其编写为具有 CTE 的 SQL 函数/存储过程,然后将其映射到您的 EF 上下文(假设您使用的是 EF,因为您提到了 SQL)。


如果您正在寻找可以转换为递归 SQL 调用的 LINQ 之类的东西,那么没有这样的解决方案。最好的办法是将所有数据拉入内存并在那里进行递归,或者在每个级别执行一次查询。

【讨论】:

  • 与我合作的技术晦涩的企业认为实体框架很糟糕,宁愿用自定义代码重新解决这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多