如何做Linq GroupJoin自我填充儿童/父母财产?

时间:2011-12-22 15:31:47

标签: c# linq join

我有以下课程

public class OrderItem
{
    public Guid ID { get; set; }
    public Guid? ParentID { get; set; }
    public IEnumerable<OrderItem> Children { get; set; }
    public OrderItem Parent { get; set; }
}

我最初从数据库和数组中获取它们。

OrderItem[] arrOrderItems = ctx.Database.SqlQuery<OrderItem>(orderItemsQuery).ToArray();

现在我想链接这些类,以便我的基础数组仍包含所有项目,但每个项目都设置了导航属性(Children,Parent)。

是否有提供此功能的Linq功能?

我的初衷是做一个GroupJoin来填补孩子,然后加入填充父母。我在下面有我的示例GroupJoin代码。我无法弄清楚如何让groupjoin返回父对象。它试图返回 IEnumerable&lt; IEnumerable&lt; OrderItem&gt; &GT;

arrOrderItems = arrOrderItems.GroupJoin(arrOrderItems, 
                                        x => x.ID, x => x.ParentID, 
                                        (parent, children) => 
                                        parent.Children = children);

有什么想法吗?

编辑:

我只想找到更好(更快)的方法来做到这一点

foreach(OrderItem item in arrOrderItems)
{
    if (item.ParentID.HasValue)
        item.ParentOrderItem = arrOrderItems.Where(x => x.ID == item.ParentID.Value).FirstOrDefault();

    item.Children = arrOrderItems.Where(x => x.ParentID.HasValue && x.ParentID.Value == item.ID).ToArray();
}

1 个答案:

答案 0 :(得分:6)

不确定在GroupJoin中分配子数组是一个非常好的做法,但要实现你想要的,你只需将代码更改为:

  var result = arrOrderItems.GroupJoin( arrOrderItems,
                                        x => x.ID, x => x.ParentID,
                                        ( parent, children ) => { parent.Children = children; return parent; } );

如果要重新分配arrOrderItems,还必须添加.ToArray(),如

  arrOrderItems = arrOrderItems.GroupJoin( arrOrderItems,
                                           x => x.ID, x => x.ParentID,
                                           ( parent, children ) => { parent.Children = children; return parent; } ).ToArray();

我认为更好的做法是将实际执行分配的代码分开,如此

foreach ( var pair in arrOrderItems.GroupJoin( arrOrderItems,
                                               x => x.ID, x => x.ParentID,
                                               ( parent, children ) => Tuple.Create( parent, children ) ) ) {

  var parent = pair.Item1;
  var children = pair.Item2;

  parent.Children = children;
  foreach ( var child in children )
    child.Parent = parent;
  }