NHibernate Fetch/FetchMany 结果集中重复,如何使用 ToFuture() 修复

标签 nhibernate nhibernate-mapping queryover

我对使用 NHibernate 比较陌生,并且遇到了一个我似乎无法解决的缺点。我有一个对象树,我希望在一次往返中从数据库中检索它,但最终得到笛卡尔积。

我尝试检索的对象称为 'AccountGroup''Concern''Advertiser'' Product',我只想获取事件用户有权访问的那些对象。

我的初始查询如下所示:

using (var session = OpenSession())
{
    return session.Query<AccountGroupEntity>()
        .FetchMany(a => a.Planners)
        .Where(a => a.Planners.Any(p => p.Id == userId))
        .FetchMany(a => a.Concerns)
        .ThenFetchMany(c => c.Advertisers)
        .ThenFetch(a => a.Products)
        .ToList();
}

这不起作用,因为它将返回笛卡尔积,并且生成的实体将包含许多重复项。

但是,我不知道如何解决这个问题。我已经看到 ToFuture() 方法允许我在同一往返中执行多个查询,但我不知道如何配置我的 ToFuture()以正确填充所有子集合的方式进行查询。

任何人都可以阐明如何使用 ToFuture 在单个查询中获取整个树而不重复吗?

最佳答案

我确实有这个主题的答案,我确实使用的解决方案。但它最后的意思是“不要使用 Fetch”——以不同的方式进行。所以,请至少将其作为一个建议。

查看此问答:

How to Eager Load Associations without duplication in NHibernate?

小引用:

Fetching Collections is a difficult operation. It has many side effects (as you realized, when there are fetched more collections). But even with fetching one collection, we are loading many duplicated rows.

换句话说,获取是一项脆弱的功能,我想说,在极少数情况下应该明智地使用它。那么该用什么呢?怎么解决?

从内置 NHibernate 功能中获益:

19.1.5. Using batch fetching

NHibernate can make efficient use of batch fetching, that is, NHibernate can load several uninitialized proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.

Batch fetching for classes/entities is easier to understand. Imagine you have the following situation at runtime: You have 25 Cat instances loaded in an ISession, each Cat has a reference to its Owner, a Person. The Person class is mapped with a proxy, lazy="true". If you now iterate through all cats and call cat.Owner on each, NHibernate will by default execute 25 SELECT statements, to retrieve the proxied owners. You can tune this behavior by specifying a batch-size in the mapping of Person:

<class name="Person" batch-size="10">...</class>

NHibernate will now execute only three queries, the pattern is 10, 10, 5.

You may also enable batch fetching of collections. For example, if each Person has a lazy collection of Cats, and 10 persons are currently loaded in the ISesssion, iterating through all persons will generate 10 SELECTs, one for every call to person.Cats. If you enable batch fetching for the Cats collection in the mapping of Person, NHibernate can pre-fetch collections:

<class name="Person">
    <set name="Cats" batch-size="3">
        ...
    </set>

根据我的经验,这种方法是无价的。对我们有用的设置是 batch-size="25"

如果您请求任何类型的实体(通过 session.Get() 或 .QueryOver()...) - 直到 session 打开,我们第一次接触相关引用或集合 -它分几批加载...没有 1 + N SELECT 问题...

摘要:使用 batch-size="x" 标记所有类和所有集合(x 可能是 25)。这将支持对根实体的干净查询 - 在 session 打开之前,所有相关内容都会加载到几个选择中。 x 可以调整,有些可能更高......

关于NHibernate Fetch/FetchMany 结果集中重复,如何使用 ToFuture() 修复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28348830/

相关文章:

c# - 将 Nhibernate 结果转换为 IDictionary<string,int>

NHIbernate 3.0 - QueryOver,使用具有不同和顺序的相同投影会引发 sql 错误

c# - 需要nHibernate指南来做CRUD

asp.net - 如何关闭 INFO 级别的 NHibernate 日志记录?

NHibernate 自定义集合类型

c# - 在使用 Fluent NHibernate 映射时对接口(interface)进行编程

NHibernate session 不缓存

nhibernate - 如何让 NHibernate 聚合函数 sum() 返回小数?

unit-testing - 单元测试流畅的 NHibernate。需要帮助理解测试期间发生的异常

asp.net-mvc - NHibernate QueryOver 与WhereRestriction 为 OR