【问题标题】:How to Eager Load Associations without duplication in NHibernate?如何在 NHibernate 中不重复地渴望加载关联?
【发布时间】:2014-01-25 01:54:36
【问题描述】:

我需要加载一个包含这么多孩子和孩子的孩子的非常大的对象的列表。最好的方法是什么?

我使用的是 Oracle 11g 数据库,我编写了以下方法,但它会导致笛卡尔积(重复结果):

 public IList<ARNomination> GetByEventId(long eventId)
        {
            var session = this._sessionFactory.Session;

            var nominationQuery = session.Query<ARNomination>().Where(n => n.Event.Id == eventId);

            using (var trans = session.Transaction)
            {
                trans.Begin();

                // this will load the Contacts in one statement
                nominationQuery
                    .FetchMany(n => n.Contacts)
                    .ToFuture();

                // this will load the CustomAttributes in one statement
                nominationQuery
                    .FetchMany(n => n.CustomAttributes)
                    .ToFuture();

                // this will load the nominations but joins those two tables in one statement which results in cartesian product
                nominationQuery
                    .FetchMany(n => n.CustomAttributes)
                    .FetchMany(n => n.Contacts)
                    .ToFuture();

                trans.Commit();
            }

            return nominationQuery.ToList();
        }

【问题讨论】:

标签: nhibernate orm future eager-loading cartesian-product


【解决方案1】:

获取 Collections 是一项困难的操作。它有许多副作用(正如您所意识到的,当获取更多集合时)。但即使获取一个集合,我们也会加载许多重复的行。

一般来说,对于集合加载,我建议使用批处理。这会执行更多的 SQL 查询...但不是那么多,更重要的是,您可以在根列表ARNomination 上进行分页。

见:19.1.5. Using batch fetching您可以找到更多详细信息。

您必须使用属性batch-szie="25" 标记您的集合和/或实体。

xml:

<bag name="Contacts" ... batch-size="25">
...

流利:

HasMany(x => x.Contacts)
  ...
  .BatchSize(25)

请在这里检查几个参数:

【讨论】:

  • 我需要加载一个包含这么多孩子和孩子的孩子的非常大的对象的列表。最好的方法是什么?
  • 我根据我的经验告诉你...我尝试了很多方法...但最好的方法就是使用批处理。让我们这样想:通过批处理,我们将使所有实体都变亮(我的意思是懒惰地引用列表和实体)。但是一旦我们需要一个实体的列表......具有许多相关的集合 atc..batch-size 将减少 sql 查询的数量,而我们仍然要求一个 simple 对象。我尝试了其他方式,获取,不懒惰..等,但最后它打破了所有的灵活性。我们确实在任何地方都使用批量大小的映射......而且我们确实具有灵活性;)
  • 谢谢,您有完整的使用 Fluent NHibernate 进行批处理的示例吗?
  • 您的任何收藏都没有设置.BatchSize(25)。而已。没有更多的映射。从那一刻起,NHibernate 将按照 19.1.5 nhforge.org/doc/nh/en/index.html#performance-fetching-batch 中的描述运行。使用此功能非常容易。只是玩数字...对我来说 25 还可以,并且成为标准;)(当然,从那一刻起不要获取收藏)
  • 这个功能给我留下了深刻的印象,正在努力使用 Eager Loading 和 Distinct Root Entity Transformer 加载非常深和复杂的对象图。我正在经历子集合的大量重复,这使整个对象图膨胀。删除了急切的加载和实施批处理 - 整个事情的填充速度要快得多! +1
【解决方案2】:

我同意@RadimKöhler,只要您急切加载多个集合,那么总会出现笛卡尔积。为了选择合适的批量大小,我可能会选择与page size 相同,因为它感觉不错......(虽然没有证据表明原因)

还有另一种您可能觉得更合适的技术,那就是阅读此博客post by Ayende,它向您展示了如何同时发送两个未来查询来急切加载灵魂工作要加载的多个集合每个集合单独。

无论您采取哪种方式,我建议您在结果中使用分析器,看看哪种方式更适合您...

【讨论】:

  • Ayende 帖子的链接很好。我同意,页面大小是关于分析......正是
猜你喜欢
  • 2011-01-11
  • 2013-02-17
  • 1970-01-01
  • 2015-02-24
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
相关资源
最近更新 更多