Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查询子项及其子项,直到没有子项为止_C#_Asp.net Mvc_Linq_Entity Framework - Fatal编程技术网

C# 查询子项及其子项,直到没有子项为止

C# 查询子项及其子项,直到没有子项为止,c#,asp.net-mvc,linq,entity-framework,C#,Asp.net Mvc,Linq,Entity Framework,假设我们有一个具有以下属性的实体: public class Foo { public int Id { get; set; } public string Name { get; set; } public int? ParentId { get; set; } } 子对象是具有非空ParentId的任何Foo。可以有多个级别的父/子关系,此时最多有5个级别 有没有一种简单的LINQ方法或通用方法,可以从一个Foo开始,得到它的所有孩子、孩子的孩子、孩子的孩子

假设我们有一个具有以下属性的实体:

public class Foo    
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
}
子对象是具有非空ParentId的任何Foo。可以有多个级别的父/子关系,此时最多有5个级别

有没有一种简单的LINQ方法或通用方法,可以从一个Foo开始,得到它的所有孩子、孩子的孩子、孩子的孩子等等


目前,我正在循环遍历起始父级的每个子级,然后再次循环以获取该子级的所有子级,等等。这很乏味,似乎不是实现我想要的目标的正确方法。

我更喜欢维护表示层次结构中某个位置的字符串属性。例如,如果值为“/99/42”,则您知道该项属于属于99的父项42。这样做很好的原因是,您可以将整个foo集合展平,只需查询以“/99”开头的字段,就可以得到层次结构的整个分支。所以你的班级看起来是这样的:

public class Foo    
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Path { get; set; } //eg: /99/42
}
希望这能有所帮助。

因此,如果您只有一个
Foo
对象,那么不可能得到它的所有后代。至少,您还需要一个包含所有
Foo
对象的序列,以便找到将该对象作为父对象的节点,因为您的
Foo
对象尚未引用其子对象。如果你有这个序列,那么它就不是特别难了

您可以在所有foo的序列上使用
ToLookup
,为该ID值的所有子项创建ID查找:

var allFoos = new List<Foo>();

var childrenLookup = allFoos.ToLookup(foo => foo.ParentId);
var allFoos=newlist();
var childrenLookup=allFoos.ToLookup(foo=>foo.ParentId);
要获取特定子代的所有子代的序列,您现在可以进行简单的树遍历:

public static IEnumerable<Foo> Descendants(Foo foo, ILookup<int?, Foo> childrenLookup)
{
    var stack = new Stack<Foo>();
    stack.Push(foo);

    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;

        foreach (var child in childrenLookup[next.Id])
            stack.Push(child);
    }
}
公共静态IEnumerable子体(Foo-Foo、ILookup-childrenLookup)
{
var stack=新堆栈();
堆栈推送(foo);
while(stack.Any())
{
var next=stack.Pop();
其次是收益率;
foreach(childrenLookup[next.Id]中的var child)
栈.推(子);
}
}

这里有查找表来获取孩子吗?听起来你想要一个给定的“父”
Foo
并得到它的子对象,但是没有机制得到子对象。这里的数据模型允许我们爬树到父级,但不能向下遍历。我只有一个表Foo。给定一个Foo对象,为了得到它的子对象,我查询ParentId=x的所有Foo。然后,对于这些子项中的每一个,我查询ParentId=上一个父项的子项的ID,等等。我需要做什么更改以包括一个机制,该机制允许我简化获取所有子项及其子项的过程?抱歉,我忽略了这是使用实体框架。+1我喜欢这样做。我想知道是否有一个内置的方法或各种方法来实现这一点。我不知道任何内置的。但实施起来并不太难。没有比你已经在做的ParentId更难维护的了。如果你能想出一些更简单的方法,请告诉我。与其让所有ID粘在一个需要解析的字符串中,不如让所有ID都有一个
IEnumerable
(或某个特定的集合)。那么您就不必担心解析逻辑了。@Josh嗯,大多数树结构都有对其子结构的引用,可能有也可能没有对其父结构的引用。这是标准的解决方案。@Servy你提到他们的孩子是什么意思?ParentId不是对父对象的引用吗?所以,要获取所有子对象,您需要使用该parentId查询所有的foo?