2016-02-22 7 views
2

У меня есть большая серверная БД, которая имеет следующую структуру класса, который я использую:Получить все дочерние элементы в списке LINQ

public class InputClass 
{ 
    public int id { get; set; } 
    public string text { get; set; } 
    public string icon { get; set; } 
    public int? parentId { get; set; } 
} 

Как вы можете видеть, каждый элемент может иметь родительский идентификатор, который в итоге генерирует список информации, который пользователь может взаимодействовать с деревом.

Используя следующие примеры данных, в качестве примера:

var inputList = new List<InputClass>(); 
inputList.Add(new InputClass() { id = 1, text = "Item #1"}); 
inputList.Add(new InputClass() { id = 2, text = "Item #2" }); 
inputList.Add(new InputClass() { id = 3, text = "Item #3" }); 
inputList.Add(new InputClass() { id = 4, text = "SubItem #1", parentId = 1 }); 
inputList.Add(new InputClass() { id = 5, text = "SubItem #2", parentId = 1 }); 
inputList.Add(new InputClass() { id = 6, text = "SubItem #3", parentId = 2 }); 
inputList.Add(new InputClass() { id = 7, text = "Sub-Sub Item #1", parentId = 4 }); 

Я хотел бы передать ID # и получить список всех элементов, отмеченных с этим ParentID. Например, если бы я имел идентификационный номер 1, то результат должен быть следующим:

ID Name 
4 Subitem #1 
5 Subitem #2 
7 Sub-Sub Item #1 

как вы можете видеть, результат должен вернуть все, что сидит под идентификатором # 1, включая пункт с ID # 7 (даже если у него есть родительский идентификатор 4, родительский элемент №4 - №1).

Надеюсь, что вышеизложенное имеет смысл, любые идеи о том, как достичь этого в LINQ?

+1

Что вы пробовали до сих пор? Как выглядит ваша текущая лучшая попытка? Что он возвращает? – mech

+1

Возможный дубликат [Рекурсивная иерархия - Рекурсивный запрос с использованием Linq] (http://stackoverflow.com/questions/20974248/recursive-hierarchy-recursive-query-using-linq) – danish

+0

Почему это должен быть LinQ? Вы можете использовать рекурсивную функцию в этом случае. – Sakura

ответ

4

Recursive подход.

public static IEnumerable<InputClass> Recursive(List<InputClass> items, int toplevelid)  
{ 
    List<InputClass> inner = new List<InputClass>(); 
    foreach (var t in items.Where(item=>item.parentId ==toplevelid)) 
    { 
     inner.Add(t); 
     inner = inner.Union(Recursive(items, t.id)).ToList(); 
    }  

    return inner; 
} 

Работа Demo

+0

не будет ли это неудачно, если ребенок создан для следующего уровня? inputList.Add (новый InputClass() {id = 8, text = "Sub-Sub Item # 1", parentId = 7}); – Rangesh

+0

Это правда, проигнорировал этот случай. Будет соответствующим образом изменен. –

2

В этом случае:

static bool IsParent(IEnumerable<InputClass> lc, InputClass ic, int? ParentID) 
{ 
    return ic.parentId != null ? ic.parentId == ParentID || IsParent(lc, lc.First(o => o.id == ic.parentId), ParentID) : false; 
} 

int? id = 1; // Parent ID 
foreach(var i in inputList) 
{ 
    if(IsParent(inputList, i, id))) 
    { 
     // get this item 
    } 
} 


Другой путь:

static IEnumerable<InputClass> getAllChildren(IEnumerable<InputClass> lc, int? ParentID) 
{ 
    foreach (var i in lc) 
    { 
     if (i.parentId == ParentID) 
     { 
      yield return i; 
      foreach (var i2 in getAllChildren(lc, i.id)) yield return i2; 
     } 
    } 
} 

int? id = 1; // Parent ID 
foreach (var i in getAllChildren(inputList,id)) 
{ 
    // Get this Item 
} 
2
static class Program 
    { 
     public static void Main() 
     { 

      IEnumerable<InputClass> allItems = someBLL.GetAllItems(); 

      int? someParentNode = 1; 

      var allChildItems = InputClass.GetAllChildNodesRecursivrly(someParentNode, allItems); 

     } 
    } 

    public class InputClass 
    { 
     public int id { get; set; } 
     public string text { get; set; } 
     public string icon { get; set; } 
     public int? parentId { get; set; } 

     public static IEnumerable<InputClass> GetAllChildNodesRecursivrly(int? ParentId,IEnumerable<InputClass> allItems) 
     { 
      var allChilds = allItems.Where(i => i.parentId == ParentId); 

      if (allChilds==null) 
      { 
       return new List<InputClass>(); 
      } 

      List<InputClass> moreChildes = new List<InputClass>(); 
      foreach (var item in allChilds) 
      { 
       moreChildes.AddRange(GetAllChildNodesRecursivrly(item.id,allItems)); 
      } 

      return allChilds.Union(moreChildes); 
     } 
    } 
-2

Я думаю, что все, что вам нужно написать, - это выражение лямбда.

var results = inputList.Where(x => x.parentId == 1) 
+0

Это не относится к многоуровневому ребенку – Sakura

Смежные вопросы