如何使用 LINQ to Entity 选择递归嵌套实体
我有一个名为 Category 的实体,该实体包含一个名为 ChildCategories 的 IEnumerable。一个类别可以有这些子类别,这些子类别可以有自己的子类别,依此类推。
假设我已经选择了顶级父类别,我想获取所有子类别及其子类别等,以便我拥有该类别的所有分层子类别。我希望将其扁平化并与初始类别一起返回。我尝试过创建类似
public static IEnumerable<T> AllChildren<T>(this IEnumerable<T> items,
Func<T, IEnumerable<T>> children, bool includeSelf)
{
foreach (var item in items)
{
if (includeSelf)
{
yield return item;
}
if (children != null)
{
foreach (var a in children(item))
{
yield return a;
children(a).AllChildren(children, false);
}
}
}
}
使用 SelectMany 方法后会变得扁平的东西,但还没有完全明白。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
仅仅使用 LINQ 是无法完成这样的事情的; LINQ 不支持开箱即用地遍历未知级别的节点。
此外,您没有任何真正的方法来展平结构,所需的属性数量未知(因为它与树深度相关,而树深度也是未知的)。
我建议使用 C# 中的迭代器 来压平树,诸如此类像这样:
然后,您可以调用扩展方法并将结果放入
List
中;它和你能得到的一样平坦。请注意,您可以很容易地抛出
StackOverflowException
如果层次结构足够深。为此,您确实想使用这种非递归方法:Stack
实例位于堆上而不是调用堆栈上,因此您不会耗尽调用堆栈空间。此外,您还可以将
Stack
更改为Queue
如果您需要不同的返回语义(或者您可以以不同的方式遍历子级),如果您需要特定的顺序。如果您需要非常具体的顺序,我建议仅在您有大量需要遍历的项目(这使得调用
OrderBy
对返回值禁止。You won't be able to do something like this with just LINQ alone; LINQ doesn't have any support for traversing an unknown level of nodes out-of-the-box.
Additionally, you don't have any real way of flattening the structure, the number of properties that is required is unknown (as it's tied to the tree depth, which is also unknown).
I'd recommend using iterators in C# to flatten the tree, something like this:
Then, you can call the extension method and place the results in a
List<T>
; it's about as flat as you are going to get.Note, you could very easily throw a
StackOverflowException
if the hierarchy is deep enough. To that end, you'd really want to use this non-recursive method:The
Stack<T>
instance lives on the heap and not on the call stack, so you won't run out of call stack space.Also, you can change the
Stack<T>
toQueue<T>
if you want different return semantics (or you can traverse through the children in different ways) if you require a certain order.If you need a very specific order, I'd only recommend changing the ordering in the method if you have a large number of items that need to be traversed which makes calling
OrderBy
on the return value prohibitive.在他的博客文章 遍历层次结构LINQ 到层次结构
, Arjan Einbu 描述了一种扁平化层次结构以方便查询的方法:
casperOne 在他的回答中也描述了这一点,以及尝试使用 LINQ 直接遍历层次结构所固有的问题。
In his blog post Traverse a hierarchical structure with LINQ-to-Hierarchical
, Arjan Einbu describes a method of flattening hierarchies for ease of querying:
casperOne describes this in his answer as well, along with the problems inherent in trying to traverse the hierarchy directly using LINQ.
casperOnes 代码存在一些问题。这有效:
There where some problems with casperOnes code. This works: