C# 将层次结构展平为特定排序的列表
我有一个简单的人员层次结构(EntityFramework Codefirst)C# 将层次结构展平为特定排序的列表,c#,linq,ef-code-first,C#,Linq,Ef Code First,我有一个简单的人员层次结构(EntityFramework Codefirst) 公共类人物 { [关键] 公共int Id{get;set;} public int?ParentId{get;set;} [必需] 公共字符串名称{get;set;} //航行 [ForeignKey(“ParentId”)] 公共虚拟人父项{get;set;} 公共虚拟ICollection子项{get;set;} } 我的目标: 我需要一个方法来创建一个列表,该列表(1)按父级进行聚类,并(2)按名称的字母
公共类人物
{
[关键]
公共int Id{get;set;}
public int?ParentId{get;set;}
[必需]
公共字符串名称{get;set;}
//航行
[ForeignKey(“ParentId”)]
公共虚拟人父项{get;set;}
公共虚拟ICollection子项{get;set;}
}
我的目标:
我需要一个方法来创建一个列表
,该列表(1)按父级进行聚类,并(2)按名称的字母顺序对每个级别进行排序:
示例输出:
- 阿尔弗雷德
- 本(阿尔弗雷德之子)
- 马里恩(阿尔弗雷德的女儿)
- 拉尔夫(阿尔弗雷德之子)
- 克里斯汀
- 爱丽(克里斯蒂娜的女儿)
- Dave
- 多丽丝
- 詹姆斯(多丽丝之子)
- 克拉斯(多丽丝之子)
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;
}
列出排序人员(列出人员)
{
列表结果=新列表();
foreach(people.OrderBy(\u=>\ uu.Name.ToList()中的Person p)
{
结果:添加(p);
result.AddRange(p.Children.OrderBy(=>\u0.Name.ToList());
}
返回结果;
}
这样行吗
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;
}
列出排序人员(列出人员)
{
列表结果=新列表();
foreach(people.OrderBy(\u=>\ uu.Name.ToList()中的Person p)
{
结果:添加(p);
result.AddRange(p.Children.OrderBy(=>\u0.Name.ToList());
}
返回结果;
}
这只在有两个级别的情况下有效,我不知道如何将其转换为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将如何处理它。这只在有两个级别的情况下有效,我不知道如何转换为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);
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;
此查询首先创建一个列表,其中每个项都有子项和父项。然后,它首先根据父对象进行排序,然后根据子对象进行排序。然后是第三个“out”属性,它定义了行的用途
我知道这可以很容易地转换为有效的SQL,但我不确定EF将如何处理它。这正是我想要的!!谢谢你,克林特!这里面有孩子吗?是的,只要他们在“人”里面,那正是我想要的!!谢谢你,克林特!这是孩子们的名单吗?是的,只要他们在“人物”嗨,谢谢你的回答。这就是我会想到的。又好又干净。但我更喜欢克林特的答案。但再次感谢!嗨,阿特姆,谢谢你的回答。这就是我会想到的。又好又干净。但我更喜欢克林特的答案。但再次感谢!嗨,欣快,到目前为止我还没有尝试过你的解决方案。我第一次看到Clint的答案,就知道这就是我一直在寻找的代码。不过你的头发看起来也很棒。非常感谢你的努力!嗨,欣快,到目前为止我还没有尝试过你的解决方案。我第一次看到Clint的答案,就知道这就是我一直在寻找的代码。不过你的头发看起来也很棒。非常感谢你的努力!
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;