Billa
Billa

Reputation: 5266

Recursive Hierarchical Parent child

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?

Upvotes: 5

Views: 8467

Answers (3)

Kosala W
Kosala W

Reputation: 2143

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. )

Upvotes: 0

Alex Siepman
Alex Siepman

Reputation: 2598

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.

Upvotes: 0

Eren Ers&#246;nmez
Eren Ers&#246;nmez

Reputation: 39085

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

Upvotes: 7

Related Questions