将层次结构展平为专门排序的列表

Flatten a hierarchy as specifically sorted list

我有一个简单的人员层次结构 (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; }
}

我的目标:

我需要一种创建 List<Person> 的方法,它 (1) 按 parent 聚类并且 (2) 在每个级别 按名称字母顺序排序 :

示例输出:

Alfred、Christine、Dave 和 Doris 都是 parent。它们按字母顺序排序。他们所有人都有 children(Dave 除外)。 children 也按字母顺序排序(在列表中它们显示为 "grouped" 和 parent)。 "son of" 和 "daughter of" 只是给你们的评论(结果列表中不需要这个)。

我可以轻松地创建这种带有嵌套循环的列表。但我相信这不会非常有效或优雅。但也许我错了。

你们中有人有好的 idea/suggestion(也许是 LINQ)吗?谢谢!!

哦,我应该提一下,层次结构只有 2 层。所以,只有 parents 和 children(但没有孙子)。

这行得通吗?

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;
}

这只有在有两个级别时才有效,我不知道这如何转化为 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);

此查询首先创建列表,其中每个项目都有 child 和 parent。然后它首先根据 parent 排序,然后根据 child 排序。然后是第三个 "out" 属性 定义该行的用途。

我知道这可以很容易地转换为有效 SQL,但我不确定 EF 将如何处理它。

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;