Как сделать Linq GroupJoin на себя, чтобы заполнить дочерние / родительские свойства? - PullRequest
3 голосов
/ 22 декабря 2011

У меня есть следующий класс

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();

Теперь я хочу связать классы так, чтобы моиБазовый массив все еще содержит ВСЕ элементы, но каждый элемент имеет свои навигационные свойства (Дети, Родитель).

Существуют ли какие-либо функции Linq, обеспечивающие эту функцию?

Моя первоначальная мысль заключалась вGroupJoin, чтобы заполнить детей, а затем присоединиться, чтобы заполнить родителей.У меня есть мой пример кода GroupJoin ниже.Я не мог понять, как заставить groupjoin вернуть родительский объект.Он пытается вернуть IEnumerable >

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 Ответ

6 голосов
/ 22 декабря 2011

Не уверен, что присвоение дочернего массива внутри 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;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...