如何使用检索到的分层结果集创建对象

本文关键字:结果 创建对象 分层 何使用 检索 | 更新日期: 2023-09-27 18:35:54

我正在使用C#语言。我的问题是我不知道如何将检索到的分层结果集存储到我的对象。

这是我的对象:

public class CategoryItem
{
    public string Name { get; set; }
    public int CategoryID { get; set; }
    public int ParentID { get; set; }
    public List<CategoryItem> SubCategory = new List<CategoryItem>();
    public List<CategoryItem> GetSubCategory()
    {
        return SubCategory;
    }
    public void AddSubCategory(CategoryItem ci)
    {
        SubCategory.Add(ci);
    }
    public void RemoveSubCategory(CategoryItem ci)
    {
        for (int i = 0; i < SubCategory.Count; i++)
        {
            if (SubCategory.ElementAt(i).CategoryID == ci.CategoryID)
            {
                SubCategory.RemoveAt(i);
                break;
            }
        }
    }
}

这是我从 MSSQL 服务器检索数据集的示例

ID  PrntID  Title   
_______ _______     
1   0   Node1   
2   1   Node2   
3   1   Node3   
4   2   Node4   
5   2   Node5   
6   2   Node6   
7   3   Node7   
8   4   Node8   
9   4   Node9   
10  9   Node10

树视图便于参考

Node 1
-Node 2
--Node 4
---Node 8
---Node 9
----Node 10
--Node 5
--Node 6
-Node 3
--Node 7

我的问题是如何将此结果存储到我的"类别项目对象"中。我不知道我需要为此使用迭代吗?特别是当节点深度为 2 级时。我想像这样存储它:

List<CategoryItem> items = new List<CategoryItem>();

有了这个,我可以挖掘"items"对象中的每个对象,并且我可以使用类的 GetSubCategory() 方法访问其子类别/子/子。这可能吗?

如何使用检索到的分层结果集创建对象

如果您知道在 DataSet 中,节点永远不会出现在其父节点之前,则可以使用此代码。在这里,您可以跟踪字典中已读取的项目,以便查找新读取节点的父节点。如果找到父项,则将新项添加到其子项,否则它是第一级节点。

    public static List<CategoryItem> LoadFromDataSet(DataSet aDS)
    {
        List<CategoryItem> result = new List<CategoryItem>();
        Dictionary<int, CategoryItem> alreadyRead = new Dictionary<int, CategoryItem>();
        foreach (DataRow aRow in aDS.Tables["YourTable"].Rows)
        {
            CategoryItem newItem = new CategoryItem();
            newItem.CategoryID = (int)aRow["ID"];
            newItem.ParentID = (int)aRow["PrntID"];
            newItem.Name = (string)aRow["Title"];
            alreadyRead[newItem.CategoryID] = newItem;
            CategoryItem aParent;
            if (alreadyRead.TryGetValue(newItem.ParentID, out aParent))
                aParent.AddSubCategory(newItem);
            else
                result.Add(newItem);
        }
        return result;
    }

如果我的假设不正确(即节点有可能出现在 DataSet 中,先于其父节点),您必须首先读取所有节点(并将它们放入字典中),然后遍历同一个字典以构建结果。像这样:

    public static List<CategoryItem> LoadFromDataSet(DataSet aDS)
    {
        List<CategoryItem> result = new List<CategoryItem>();
        Dictionary<int, CategoryItem> alreadyRead = new Dictionary<int, CategoryItem>();
        foreach (DataRow aRow in aDS.Tables["YourTable"].Rows)
        {
            CategoryItem newItem = new CategoryItem();
            newItem.CategoryID = (int)aRow["ID"];
            newItem.ParentID = (int)aRow["PrntID"];
            newItem.Name = (string)aRow["Title"];
            alreadyRead[newItem.CategoryID] = newItem;
        }
        foreach (CategoryItem newItem in alreadyRead.Values)
        {
            CategoryItem aParent;
            if (alreadyRead.TryGetValue(newItem.ParentID, out aParent))
                aParent.AddSubCategory(newItem);
            else
                result.Add(newItem);
        }
        return result;
    }

您必须编写递归代码才能实现此目的。

//First of all, find the root level parent
int  baseParent = "0"; 
// Find the lowest root parent value
 foreach (var selection in collection)
 {
     //assign any random parent id, if not assigned before
      if (string.IsNullOrEmpty(baseParent))
        baseParent = selection["PrntID"];
     //check whether it is the minimum value
     if (Convert.ToInt32(selection["PrntID"]) < Convert.ToInt32(baseParent))
       baseParent = selection["PrntID"];
 }
//If you are sure that your parent root level node would always be zero, then you could   //probably skip the above part.
//Now start building your hierarchy
foreach (var selection in collection)
{
  CategoryItem item = new CategoryItem();
  //start from root
  if(selection["Id"] == baseParentId)
  {
    //add item property
    item.Id = selection["id];
    //go recursive to bring all children
    //get all children
    GetAllChildren(item , collection);
  }
}

private void GetAllChildren(CategoryItem parent, List<Rows> Collection)
{
  foreach(var selection in Collection)
  {
     //find all children of that parent
     if(selection["PrntID"] = parent.Id)
     {
       CategoryItem child = new CategoryItem ();
       //set properties
       child.Id = selection["Id"];
       //add the child to the parent
       parent.AddSubCategory(child);
       //go recursive and find all child for this node now
       GetAllChildren(child, Collection);
     }
   }
}

注意:这不是完全有效的代码。但这会让你深入了解如何四处走动并构建必须表示为对象的分层数据结构。

将表加载到数据表中,然后找到根节点并创建根对象

DataRow[] rootRow = table.Select("PrntID = 0");
CategoryItem root = new CategoryItem() { CategoryID = (int)rootRow[0]["ID"].ToString(), Name = rootRow[0]["Title"].ToString(), ParentID = (int)rootRow[0]["PrntID"].ToString() };

然后你需要调用递归方法来添加子类别,

GetCategoryItem((int)rootRow[0]["ID"].ToString(), root);

根据需要更改以下方法。

public void GetCategoryItem(CategoryItem parant)
{
    DataRow[] rootRow = table.Select("PrntID =" + parant.CategoryID);
    for (int i = 0; i < rootRow.Length; i++)
    {
        CategoryItem child = new CategoryItem() { CategoryID = (int)rootRow[i]["ID"].ToString(), Name = rootRow[i]["Title"].ToString(), ParentID = (int)rootRow[i]["PrntID"].ToString() };
        GetCategoryItem(child);
        parant.SubCategory.Add(child);
    }
}