2015-04-07 62 views
0

我有一個簡單的人員層次結構(EntityFramework Codefirst)。將層次結構展平爲明確排序的列表

public class Person 
{ 
    [Key] 
    public int Id { get; set; } 

    public int? ParentId { get; set; } 

    [Required] 
    public string Name { get; set; } 

    // Navigation 

    [ForeignKey("ParentId")] 
    public virtual Person Parent { get; set; } 

    public virtual ICollection<Person> Children { get; set; } 
} 

我的目標:

我需要創建這是(1)由家長聚集和(2)按字母順序排序按名稱每個級別一個List<Person>的方法:

輸出示例:

  • Alfred
  • 奔(阿爾弗雷德的兒子)
  • 馬里昂(阿爾弗雷德的女兒)
  • 拉爾夫(阿爾弗雷德的兒子)
  • 盟友(恭的女兒)
  • 戴夫
  • 多麗絲
  • 詹姆斯(多麗絲的兒子)
  • 克拉斯(多麗絲的兒子)

阿爾弗雷德,恭,戴夫和多麗絲都是父母。它們按字母順序排序。他們都有孩子(戴夫除外)。孩子們也按照字母順序排序(並且在列表中他們出現「與父母分組」)。 「的兒子」和「女兒」只是你們的評論(我不需要在結果列表中)。

我可以很容易地創建這種類型的嵌套循環列表。但我相信這不會很有效率或優雅。但也許我錯了。

你們有沒有人有一個好主意/建議(也許與LINQ)?謝謝!!

哦,我應該提到,層次結構只有2級。所以,只有父母和孩子(但沒有孫子)。

回答

2
var sortedPeople = 
    from p in people 
    orderby (p.Parent == null ? p.Name : p.Parent.Name), 
     p.Parent == null ? 1 : 2, // this ensures parents appear before children 
     p.Name 
    select p; 
+0

這就是我正在尋找的!謝謝,克林特! – Ingmar

+0

這是否列出孩子? – artm

+0

是的,只要他們在「人」 –

2

這項工作?

List<Person> sortPeople(List<Person> people) 
{ 
    List<Person> result = new List<Person>(); 

    foreach (Person p in people.OrderBy(_ => _.Name).ToList()) 
    { 
     result.Add(p); 
     result.AddRange(p.Children.OrderBy(_ => _.Name).ToList()); 
    } 

    return result; 
} 
+0

嗨,謝謝你的回答。這是我會想出來的。很好,很乾淨。但我更喜歡克林特的回答。但再次感謝! – Ingmar

1

這隻能如果有兩個層面,我不知道如何轉換到SQL:

var parents = people.Select(person=>person.Parent == null); 
var parentsWithChildrenGrouped = 
    parents 
    .SelectMany(parent=>parent.Children.Select(child=>new {Parent = parent, Child = child, Out = child})) 
    .Union(parents.Select(parent => new {Parent = parent, Child = null, Out = parent})) 
    .OrderBy(x=>x.Parent).ThenBy(x=>x.Child) 
    .Select(x=>x.Out); 

此查詢首先創建一個列表,其中每個項目都有兩個孩子,它的父。然後它首先根據父母然後由孩子分類。然後有第三個「out」屬性定義該行的用途。

我知道這可以很容易地轉換爲有效的SQL,但我不知道EF如何處理它。

+0

嗨Euphoric,我到目前爲止還沒有嘗試過你的解決方案。我第一次看到克林特的回答,並知道這是我一直在尋找的代碼。雖然你的看起來很棒。非常感謝你的努力! – Ingmar