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

如何在NHibernate中不重复地加载关联?,nhibernate,orm,future,eager-loading,cartesian-product,Nhibernate,Orm,Future,Eager Loading,Cartesian Product,我需要加载一个包含这么多子对象和子对象的非常大的对象列表。最好的方法是什么 我使用的是Oracle 11g数据库,我编写了以下方法,但它会产生笛卡尔积(重复结果): public IList GetByEventId(长eventId) { var session=this.\u sessionFactory.session; var namignionquery=session.Query()。其中(n=>n.Event.Id==eventId); 使用(var trans=session.T

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

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

public IList GetByEventId(长eventId)
{
var session=this.\u sessionFactory.session;
var namignionquery=session.Query()。其中(n=>n.Event.Id==eventId);
使用(var trans=session.Transaction)
{
trans.Begin();
//这将在一条语句中加载联系人
提名查询
.FetchMany(n=>n个联系人)
.ToFuture();
//这将在一条语句中加载CustomAttributes
提名查询
.FetchMany(n=>n.CustomAttributes)
.ToFuture();
//这将加载指定,但将这两个表合并到一个语句中,从而生成笛卡尔积
提名查询
.FetchMany(n=>n.CustomAttributes)
.FetchMany(n=>n个联系人)
.ToFuture();
trans.Commit();
}
返回NagnationQuery.ToList();
}
获取集合是一项困难的操作。它有许多副作用(正如您所意识到的,当获取更多集合时)。但即使获取一个集合,我们也会加载许多重复的行

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

请参阅:您可以找到更多详细信息

您必须使用属性
batch szie=“25”
标记集合和/或实体

xml:

请检查以下几个参数:


我同意@RadimKöhler的观点,只要你想加载多个集合,笛卡尔积就会出现。为了选择合适的批处理大小,我可能会选择与
页面大小相同的批处理大小,因为它感觉正确。。。(但没有证据表明原因)

你可能会觉得另一种技术更合适,那就是阅读本博客,它向你展示了如何在未来同时发送两个查询以加载多个集合,而soul的工作是单独加载每个集合


但是,无论您选择哪种方法,我建议在结果中使用探查器,以查看哪种方法更适合您……

我需要加载一个包含如此多子对象和子对象的非常大对象的列表。最好的方法是什么?我根据我的经验告诉你。。。我试过很多方法。。。但最好是简单地使用批处理。让我们这样考虑:通过批处理,我们将使所有实体都变轻(我的意思是懒洋洋地引用列表和实体)。但一旦我们需要一份救援实体的名单。。。有很多相关的收藏。。批处理大小将减少sql查询的数量,而我们仍然需要一个简单的对象。我尝试了其他的方法,吸引人,而不是懒惰。。等等,但最后它打破了所有的灵活性。我们确实在映射中使用了批量大小。。。我们确实有灵活性;)谢谢,您有使用Fluent NHibernate进行批处理的完整示例吗?除了设置
.BatchSize(25)
之外,您的任何集合都没有其他内容。就这样。没有更多的映射。从那时起,NHibernate的行为将如19.1.5所述。此功能的使用非常简单。只是玩一下这个号码。。。对我来说,25还可以,并且成为标准;)(当然,从那一刻起,不要获取集合)这个特性给人留下了深刻的印象,我们正在努力用急切的加载和独特的根实体转换器加载非常深刻和复杂的对象图。我经历了大量重复的子集合,使整个对象图膨胀。删除了急切的加载和实现批处理-整个过程的填充速度要快得多+1链接到Ayende post的链接不错。页面大小,我同意,是关于分析。。。完全可能的副本
 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();
        }
<bag name="Contacts" ... batch-size="25">
...
HasMany(x => x.Contacts)
  ...
  .BatchSize(25)