如果只给出子元素,如何在C#中构建一个树?

时间:2010-07-17 19:08:47

标签: c# nhibernate fluent-nhibernate tree

我有一组属于树的元素。我只关心祖先,我不关心孩子。例如,我希望树看起来像这样:

     
  1. 烧烤用品*
  2.  
  3. 家居清洁用品
  4.  
    1. 空气清新剂
    2.  
        1。汽车Airfreshner *
       
    3. 纸巾*
     
  5. 用具
  6.  
    1. 叉*

    我给出的唯一输入是加星标的元素。所以我有这样的事情:

    List<Categories> categories = new List<Categories>("Forks", "Paper Towels", "Car Airfreshner", "Barbeque Supplies");
    

    类别如下:

    string Id;
    Category Parent;
    IList<Category> Children;
    Category RootNode; // e.g., "Household cleaning supplies"
    

    不幸的是,整棵树相当大...... ~17,000件物品。但是这个列表基本上没有变化,所以如果我必须做任何事情来按摩它以使访问更容易,我愿意这样做。

    我正在使用NHibernate,我尝试了几种方法:

    public IList<Categories> CompleteTree(IList<Categories> inputList) {
                var result = new List<Categories>();
                foreach (var item in inputList) {
                    var recursiveItem = categoryRepository.Get(item);
    
                    while (recursiveItem != null) {
                        result.Add(recursiveItem);
                        recursiveItem = item.Parent;
                    }
                }    
                return result;
            }
    

    无论如何,这对数据库有很大影响吗?我正在使用NHibernate 2,如果有任何光滑的代码。

    我已经看过Ayende's blog post,了,但是他正在关注儿童用品,在那里,我开始给孩子用品,我正在努力工作。或者我可能和他做同样的事情但却没有意识到这一点。

    编辑:添加categoriesRepository以使我更清楚地知道我正在访问数据库。

1 个答案:

答案 0 :(得分:0)

免责声明:由于我没有使用NHibernate的经验,我现在就出去了。

Ayende's blog post使用join fetch语句,该语句是特定于NHibernate的SQL,称为HQL。由于NHibernate只是数据库之上的另一层,并且SQL数据库不是为处理层次结构而设计的,因此仍然需要递归查询来获取整个树。

但Ayende还在one of his comments中提到,如果直接和间接关系都存储在数据库中,则查询树会更容易。他指的是这样的结构:

Ancestor                      Descendant        IsChild
-------------------------------------------------------
Household cleaning Supplies   Air fresheners    True
Household cleaning Supplies   Paper Towels      True
Household cleaning Supplies   Car Airfreshner   False
Air fresheners                Car Airfreshner   True
Utensils                      Forks             True

Ayende使用Level列来指示树中节点的深度,该列可用于限制查询中树的深度。但IsChild也将证明这一原则。

寻找祖先

鉴于后代节点 Car Airfreshner ,您可以在一个查询中选择所有祖先节点。您可以通过检查IsChild值来重建这些节点的父子关系。

SELECT * FROM TreeRelations WHERE Descendant = 'Car Airfreshner'

创建树

鉴于祖先节点家庭清洁用品,您可以通过选择单个查询中的所有后代来从此节点开始构建树。 IsChild值可用于查找父子关系。

SELECT * FROM TreeRelations WHERE Ancestor = 'Household cleaning Supplies'

两个查询合并

要获取任何给定节点的整个树,您可以组合两个查询以检索所有祖先和后代,并从中构建树:

SELECT * FROM TreeRelations WHERE Descendant = 'Entry node' OR Ancestor = 'Entry node'