Recursive Hierarchical Parent child

2020-06-04 07:46发布

I have a collection of items coming from a database which has a parentid value or null.

Here is my class design:

public class Item
{
public int id{get;set;}
public string Name{get;set;}
public int? ParentId{get;set;}
public List<Item> SubItems{get;set;}
}

I want to build a hierarchical structure of Items from the collection. Assume a collection is 100 items from which I need to construct the structure based on the ParentId mapping.

I tried this post Recursive Hierarchical Joins in C# and LINQ but it gives me an error if ParentId is null.

Also tried Build tree type list by recursively checking parent-child relationship C# , but this solution also does not work for me.

How do I achieve this?

3条回答
ゆ 、 Hurt°
2楼-- · 2020-06-04 08:33

Do you really need a setter for sub items? Also be mindful of the performance issues when you run Select* queries on SQL server.

  public List<Item> SubItems{
  get
  {
   try{
        var validParents = db.items.Where(x=>x.ParentId!=null && x.ParentId.Equals(Id)); //db is your dbcontext
        if(validParents !=null)
        {
           return validParents.ToList(); 
        }else
        {
         return null;
        } 
        catch(Exception)
        {
          return null;
        }
   }

(Note: Think of adding this to your partial entity class. Never name your entity as "Item" :).Item is a reserved word. )

查看更多
够拽才男人
3楼-- · 2020-06-04 08:36

You could use this approach:

  1. Get all the items from the database (without filling the SubItems).
  2. Build a Lookup<int?,Item> of parent ids and items with that parent id.
  3. Loop through the items and associate each item with the subitems using the lookup.

Code:

var items = // get from the database... (e.g. as a list)
var lookup = items.ToLookup(x => x.ParentId);
foreach (var item in items)
    item.SubItems = lookup[item.Id].ToList();

As @EamonNerbonne commented below, you can get the root elements as well, if you need to:

var roots = lookup[null].ToList();
查看更多
做个烂人
4楼-- · 2020-06-04 08:46

Using this Node class you can simply do this:

var flatListOfItems = GetItemsFromDatabase();
var rootNodes =Node<Item>.CreateTree(flatListOfItems, i => i.id, i => i.ParentId);

Your items doesn't need the subitems anymore because the Node class has a children and a descendants property. (Also ancestors, siblings, level etc.).

The CreateTree method results in 1 or more rootnodes. If you are sure that there is always 1 rootnode, you can do rootNodes.Single() to get the root.

查看更多
登录 后发表回答