如何在NHibernate中加载关联而不重复?

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

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

提取集合是一个困难的操作。 它有许多副作用(如你意识到,当有更多的collections) 。 但是即使拿到一个集合,我们也会加载很多重复的行。

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

参见: 19.1.5。 使用批量提取可以find更多的细节。

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

XML:

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

stream利:

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

请在这里检查几个参数:

只要你急于加载多个集合,我就会同意@ RadimKhlerler,那么笛卡尔的产品总是会发生的。 为了select一个合适的批量大小,那么我可能会select这个与page size相同,因为它只是觉得正确…(没有证据为什么)

还有另外一种技术,你可能觉得更合适,那就是阅读Ayende的博客文章,告诉你如何在同一时间发送两个未来的查询,以便加载多个集合,灵魂工作是单独加载每个集合。

然而,无论您select哪条路线,我build议您在结果中添加一个分析器,以查看哪个更适合您

Interesting Posts