4

我想创建一个类结构,它可以表示所有相同类型的对象的以下层次结构

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

数据表行具有 ID、ParentID、名称和级别

级别是 O 为 Parent , 1 为 Child 1 , 2 为 ChildA 等等

我能够将数据从数据库返回到数据表,但在那之后我正在苦苦挣扎,对于创建类结构然后填充对象的任何帮助将不胜感激

4

3 回答 3

9

这是一个关于如何使用 LINQ 执行此操作的示例。首先是一个示例数据表。我假设顶级项目的父 ID 为 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" });

表示每项数据的类:

class Item {

  public Int32 Id { get; set; }

  public String Name { get; set; }

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

}

获取特定项的子项的函数:

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

创建包含子集合的项目的函数。此函数将向下递归层次结构:

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 };
}

获取顶级项目行的函数:

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

把它们放在一起:

var items = GetTopLevelRows(dataTable)
  .Select(row => CreateItem(dataTable, row))
  .ToList();
于 2012-05-01T10:05:35.967 回答
2

鉴于上述信息,您只需一节课就可以做到这一点。

public class MyItem
{
  public IList<MyItem> ChildItems{get;set;}
}

在这里,您基本上得到了一个对象,该对象可以包含自己类型的集合作为子项,因此,这些子项也可以包含 MyItem 的集合作为子子项。

考虑以下:

var parentItem = new MyItem()
var childItem = new MyItem();
var childChildItem = new MyItem();

childItem.ChildItems.Add(childChildItem);
parentItem.ChildItems.Add(childItem);

有更好的方法来编码项目的添加,但这在逻辑上足以使概念清晰。

于 2012-05-01T09:40:16.253 回答
1

这是我的方法。

从问题中定义的数据开始:

var dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(int));
dataTable.Columns.Add("ParentId", typeof(int));
dataTable.Columns.Add("Name", typeof(String));
dataTable.Rows.Add(new Object[] { 1, 0, "Parent1" });
dataTable.Rows.Add(new Object[] { 2, 1, "Child1" });
dataTable.Rows.Add(new Object[] { 3, 2, "ChildA of Child1" });
dataTable.Rows.Add(new Object[] { 4, 2, "ChildB of Child1" });
dataTable.Rows.Add(new Object[] { 5, 1, "Child2" });
dataTable.Rows.Add(new Object[] { 6, 5, "ChildA of Child2" });
dataTable.Rows.Add(new Object[] { 7, 5, "ChildB of Child2" });  
dataTable.Rows.Add(new Object[] { 8, 0, "Parent2" });

然后这样做:

var lookup = dataTable.Rows.Cast<DataRow>().ToLookup(x => x.Field<int>("ParentId"));

Func<int, Item[]> build = null;
build = n =>
    lookup[n]
        .Select(dr => new Item()
            {
                Id = dr.Field<int>("Id"),
                Name = dr.Field<string>("Name"),
                Children = build(dr.Field<int>("Id")),
            })
            .ToArray();

var items = build(0);

这给出了:

项目

于 2018-06-16T03:36:36.227 回答