我遇到了问题。
我有一个孙子集合,我想使用 LINQ 将其转换为祖父对象的集合。子对象具有父对象的导航属性。我尝试过按祖父母名字分组,但后来我被一个字符串卡住了。
我的祖父母班级看起来像这样:
祖父类
public class GrandParentBLL
{
public GrandParentBLL()
{
Parents= new List<Parent>();
}
public int ID { get; set; }
public int Number { get; set; }
public string Name { get; set; }
public ICollection<ParentBLL> Parents{ get; set; }
}
儿童班:
Child class
public class ParentBLL
{
public ParentBLL()
{
Children= new List<Child>();
}
public int ID { get; set; }
public int Number { get; set; }
public string Name { get; set; }
public GrandParentBLL GrandParent { get; set; }
public ICollection<ChildBLL> Children { get; set; }
}
孙子班:
public class ChildBLL
{
public ChildBLL()
{
}
public int ID { get; set; }
public int Number { get; set; }
public string Name { get; set; }
public ParentBLL Parent{ get; set; }
}
现在我得到了一个孙子对象列表,其中每个对象可以有不同的父项或祖父项。我可以使用导航属性访问父级。我想获取祖父对象的列表,其中包含每个祖父项的相应子集合。
我尝试了以下方法:
var grandparents = Children.GroupBy(x => x.Parent.GrandParent).Select(d=>d.Key).ToList();
但是后来我为孙子收藏中的每个对象都得到了一个祖父对象,尽管只有 2 个不同的祖父母。
如果要获取唯一的祖父实体,则查询应为
var grandparents = grandChildren
.Select(c => c.Parent) // --> get all the grand children's parents
.Select(p => p.GrandParent) // --> get all the GrandParents from each of the Parents above
.Distinct();
更新:因此,如果父对象不保存子集合,请根据您的评论以及接受的答案。以下是为父对象添加水处理的一种方法:
IEnumerable<ParentBLL> parents = grandChildren
.Select(gc => gc.Parent)
.Distinct()
.Pipe(p => p.GrandChildren = grandChildren.Where(gc => gc.Parent.ID == p.ID).ToList());
IEnumerable<GrandParentBLL> grandparents = parents
.Select(p => p.GrandParent).Distinct()
.Pipe( gp => gp.Parents = parents.Where(p => p.GrandParent.ID == gp.ID).ToList());
该解决方案使用 .Pipe
,它"对源序列中的每个元素执行给定的操作并生成它"。这是来自MoreLinq的扩展方法。因此,您需要添加对此包的引用。
容易
从您的示例中不清楚每个类是否都有自己的直系子级集合。如果他们这样做了,答案很简单:
Dictionary<GrandParent,List<Child>> results = grandparents.ToDictionary
(
g => g,
g => g.Parents.SelectMany( p => p.Children ).ToList()
);
不那么容易
如果父母不了解他们的孩子,只有孩子知道他们的直系父母,那么还有更多的工作,我将分三个步骤带你完成:
第 1 步。首先获取一个可以重用的父母和祖父母的枚举器:
var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
.Select( p => p.GrandParent )
.Distinct();
第 2 步。现在修改代码以将grandParents
更改为Dictionary<GrandParent,List<Parent>>
:
var children = new List<ChildBLL>();
var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
.Select( p => p.GrandParent )
.Distinct()
.ToDictionary
(
g => g,
g => parents.Where( p => p.GrandParent == g )
);
第 3 步。添加代码以将Dictionary<GrandParent,List<Parent>>
转换为Dictionary<Grandparent,List<Child>>
:
var parents = children.Select( c => c.Parent ).Distinct();
var grandParents = parents
.Select( p => p.GrandParent )
.Distinct()
.ToDictionary
(
g => g,
g => parents.Where( p => p.GrandParent == g )
)
.ToDictionary
(
pair => pair.Key,
pair => pair.Value.SelectMany
(
p => children.Where( c => c.Parent == p )
)
);
完成后,您将拥有一个字典,其中键是祖父级,值是其孙子级的List<Children>
。