Reputation: 5266
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
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
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
Reputation: 39085
You could use this approach:
Lookup<int?,Item>
of parent ids and items with that parent id.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