3

我正在使用 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

我的问题是如何将此结果存储到我的“CategoryItem 对象”中。我不知道我需要为此使用迭代吗?特别是当节点为 2 级时。我想以这样的方式存储它:

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

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

4

3 回答 3

2

如果您知道在您的 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 中),您必须首先读取所有节点(并将它们放入 Dictionary),然后遍历同一个 Dictionary 以构建结果。像这样的东西:

    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;
    }
于 2012-05-31T04:55:58.913 回答
0

你必须编写递归代码来实现这一点。

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

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

于 2012-05-31T05:03:55.047 回答
0

将您的表加载到数据表中并首先找到根节点并创建根对象

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);
    }
}
于 2012-05-31T05:04:42.893 回答