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

时间:2012-05-31 03:55:46

标签: c#

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

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

3 个答案:

答案 0 :(得分: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中),则必须首先读取所有节点(并将它们放入字典中),然后循环遍历字典来构建结果。像这样:

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

答案 1 :(得分: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);
     }
   }
}

注意:这不是完全正常工作的代码。但是,这将使您了解如何绕过并构建必须表示为对象的分层数据结构。

答案 2 :(得分:0)

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

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