2012-06-19 157 views
0

我需要得到一个嵌套集合的节点,通过它深入linq。Linq无限嵌套查询

这是嵌套类:

public class Group 
{ 

    public int Id { get; set; } 

    public string Description { get; set; } 

    public int ParentId { get; set; } 

    public List<Group> Groups { get; set; } 

} 

本类的每个实例可具有组方法内的多个实例等。每个实例通过ParentId属性链接。

我需要,有一个Group类的实例,检索他的父亲。我试着用这样的:

var parent = _repositoryGroups 
.Where(g => g.Id == [my Group instance].ParentId) 
.SelectMany(g => g.Groups) 
.FirstOrDefault() 

我不知道为什么,但并不总是它找到父亲实例,并开始从第二个层面看(但是这不是一个真正的问题)。

通过这个嵌套类的所有深处找到元素的最佳方法是什么?

感谢

+2

我认为你在滥用SelectMany。如果你删除该行,它应该工作 – Schiavini

+0

我同意@Schiavini。如果没有'SelectMany',查询会返回具有所需id的第一个组(返回父亲)。从该父项中选择所有组,然后采用第一个组看起来会显示返回父项的第一个子项,而不是父项。 – SimpleVar

+0

没有'SelectMany'就无法工作。它只检索第一级别下的群组... –

回答

1

像你想获得的所有儿童的递归某一群现在听起来。

所以,你可以有:

private IEnumerable<Group> EnumerateChildren(Group parent) 
{ 
    if (parent.Groups != null) 
    { 
     foreach (var g in parent.Groups) 
     { 
      yield return g; 

      foreach (var sub in EnumerateChildren(g)) 
      { 
       yield return sub; 
      } 
     } 
    } 
} 

如果你只想得到一组特定的父:

private Group GetParent(Group child) 
{ 
    _repositoryGroups.Where(g => g.Id == child.ParentId).FirstOrDefault(); 
} 

如果你需要得到一组特定的超亲(父父父...):

private Group GetSuperParent(Group child) 
{ 
    parent = GetParent(child); 

    while (parent != null) 
    { 
     child = parent; 
     parent = GetParent(child); 
    } 

    return child; 
} 

以上这一切,我建议,如果你能做到这一点,抓住参考而不是它的Id。如果没有父亲,请将其设为null。节省了很多麻烦。很多。

+0

它是'儿童',而不是'childs' :-) – sloth

+0

@BigYellowCactus LOL谢谢。 – SimpleVar

+0

我自己一直爱上它:-) – sloth

0

如果你愿意,可以去你的结构,找到父母的最后家长,您可以使用这段代码:

var group = [my Group instance]; 

while(group.ParentId > 0) 
{ 
    group = _repositoryGroups.First(g => g.Id == group.ParentId); 
} 

这里假设你的ID是大于零,那一个id> 0将始终有一个有效的父项。

+0

没有保证有效的身份证号在零以上,也没有必要有一个父亲,这会导致'第一个'没有找到任何异常。 – SimpleVar

+0

事实上,我只是将我的假设添加到回答 – Schiavini

+0

我会考虑去FirstOrDefault,检查null,并抛出自定义异常的“RepositoryGroups corrupted-Parent not found”或类似的东西,如果你要采用假设的方法无论如何。 – SimpleVar

0

对不起,我可能没有很好地解释我的问题。我已经开发了这个解决方案鼓舞你的答案:

private static Group GetGroupFather(IEnumerable<Group> groups, Group child) 

{ 

    foreach (var group in groups) 
{ 

    // try to nested search 
    var result = GetGroupFather(group.Groups, child); 

    if (result != null) return result; 

    // check in the current level 
    if (group.Id == child.ParentId) 

     return group; 

} 

return null; 

} 

如果你有更好的解决方案使用LINQ,请让我知道。

+0

子对象根本没有变化。你不能使用'_repositoryGroups.FirstOrDefault(g => g.Id == child.ParentId)'? – Schiavini

+0

我使用孩子只是为了获得父母的ID。我不能使用你的代码,因为它只是从'_repositoryGroups'的第一级检索组,而不是从嵌套情况,例如'_repositoryGroups [0] .Groups [2] .Groups [1] .Groups [2] .id == child.ParentId' –