Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create hierarchical class structure , loop through data table and then add parent and child and return object

Tags:

c#

hierarchy

I want to create a class structure that can represent the following heirarchichal structure of objects all of the same type

-Parent1
- - Child1 
- - - ChildA of Child1
- - - ChildB of Child1
- - Child2 
- - - ChildA of Child2
- - - ChildB of Child2
- Parent2

The datatable rows have an ID, ParentID, name and level

level is O for Parent, 1 for Child 1 , 2 for ChildA and so on

I'm able to return the data from the DB to a datatable but am struggling after that any help on creating the class structure and then populating the object would be greatly appreciated

like image 243
cWilk Avatar asked Dec 16 '22 00:12

cWilk


1 Answers

Here is an example on how to do that using LINQ. First a sampe datatable. I assume that top-level items have a parent ID of 0.

var dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(Int32));
dataTable.Columns.Add("ParentId", typeof(Int32));
dataTable.Columns.Add("Name", typeof(String));
dataTable.Rows.Add(new Object[] { 1, 0, "A" });
dataTable.Rows.Add(new Object[] { 2, 1, "B" });
dataTable.Rows.Add(new Object[] { 3, 1, "C" });
dataTable.Rows.Add(new Object[] { 4, 0, "D" });
dataTable.Rows.Add(new Object[] { 5, 4, "E" });

A class to represent each item of data:

class Item {

  public Int32 Id { get; set; }

  public String Name { get; set; }

  public IEnumerable<Item> Children { get; set; }

}

A function to get the children of a specific item:

IEnumerable<DataRow> GetChildren(DataTable dataTable, Int32 parentId) {
  return dataTable
    .Rows
    .Cast<DataRow>()
    .Where(row => row.Field<Int32>("ParentId") == parentId);
}

A function to create an item including the child collection. This function will recurse down the hierarchy:

Item CreateItem(DataTable dataTable, DataRow row) {
  var id = row.Field<Int32>("Id");
  var name = row.Field<String>("Name");
  var children = GetChildren(dataTable, id)
    .Select(r => CreateItem(dataTable, r))
    .ToList();
  return new Item { Id = id, Name = name, Children = children };
}

A function to get rows of the top-level items:

IEnumerable<DataRow> GetTopLevelRows(DataTable dataTable) {
  return dataTable
    .Rows
    .Cast<DataRow>()
    .Where(row => row.Field<Int32>("ParentId") == 0);
}

Putting it all together:

var items = GetTopLevelRows(dataTable)
  .Select(row => CreateItem(dataTable, row))
  .ToList();
like image 87
Martin Liversage Avatar answered Feb 22 '23 22:02

Martin Liversage