【问题标题】:preloading a tree / hierarchy from database using NHibernate / C#使用 NHibernate/C# 从数据库预加载树/层次结构
【发布时间】:2012-07-04 16:25:30
【问题描述】:

我需要填充一些树层次结构并遍历它们以构建类别菜单。每个类别可以有超过 1 个父级。问题是如何有效地做到这一点,并尽量避免Select N+1 问题。

目前是通过使用两个表/实体来实现的:

Category
--------
ID
Title

CategoryLink
---------
ID
CategoryID
ParentID

理想情况下,我会使用普通的对象遍历来遍历节点,即通过Category.ChildCategories 等。这可以在一个 SQL 语句中完成吗?还有,这可以在 NHibernate 中完成吗?

【问题讨论】:

    标签: c# sql nhibernate hierarchy hierarchical-data


    【解决方案1】:

    Category.ChildCategories 映射上指定batch-size。这将导致 NHibernate 分批获取指定大小的子节点,而不是一次一个(这将缓解 N+1 问题)。

    如果您使用.hbm 文件,您可以像这样指定batch-size

    <bag name="ChildCategories" batch-size="30">
    

    或使用流畅的映射

    HasMany(x => x.ChildCategories).KeyColumn("ParentId").BatchSize(30);
    

    请参阅NHibernate documentation 了解更多信息。

    编辑

    好的,我相信我了解您的要求。配置如下

    HasManyToMany<Item>(x => x.ChildCategories)
        .Table("CategoryLink")
        .ParentKeyColumn("ParentId")
        .ChildKeyColumn("CategoryID")
        .BatchSize(100)
        .Not.LazyLoad()
        .Fetch.Join();
    

    您应该能够使用以下行在一次调用中获取整个层次结构。

    var result = session.CreateCriteria(typeof(Category)).List();
    

    由于某种原因,检索这样的单个类别

    var categoryId = 1;
    var result = session.Get<Category>(categoryId);
    

    导致层次结构中的每一层调用一次。我相信这仍会显着减少对数据库的调用次数,但我无法让上面的示例与对数据库的单个调用一起工作。

    【讨论】:

    • 我已经在使用批量大小了。但是,这只解决了一个级别,而不是n 级别。树可以很深,比如 3、4 甚至更多级别。理想情况下,我正在查看整个级别的 1 个查询。
    • 批量大小并不能准确地产生有效的查询计划。它产生大量的单例查找。不过,这可能是性能和工程时间之间的一个很好的权衡。
    【解决方案2】:

    这将检索所有类别及其子类别:

    var result = session.Query<Category>()
                        .FetchMany(x => x.ChildCategories)
                        .ToList();
    

    问题在于确定根类别是什么。您可以使用标志,或映射逆向集合 (ParentCategories) 并执行以下操作:

    var root = session.Query<Category>()
                      .FetchMany(x => x.ChildCategories)
                      .FetchMany(x => x.ParentCategories)
                      .ToList()
                      .Where(x => !x.ParentCategories.Any());
    

    所有排序都应该在客户端完成(即在ToList之后)

    【讨论】:

      猜你喜欢
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多