以递归方式获取LINQ中匹配的所有节点

时间:2018-02-03 23:24:36

标签: c# linq recursion

有没有办法在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级怎么样?我是用CT在SQL中完成的,但不确定在C#中使用它的正确方法。

1 个答案:

答案 0 :(得分: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之类的东西,那么就没有这样的解决方案。你得到的最好的是将所有数据拉入内存并在那里进行递归,或者每个级别执行一次查询。