2012-06-19 190 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' –