【问题标题】:Eager loading multiple child collections within a paged result渴望在分页结果中加载多个子集合
【发布时间】:2011-03-21 13:25:28
【问题描述】:

我已经远远超出了我的 NHibernate 能力,看来...

我正在尝试加载具有三个子集合的给定实体的 Top10,但 NHibernate 的 Linq 实现为我提供了正确的结果...以加载所有子集合的整个表为代价。

public class PartnerDto : BaseDto
{
    private IList<EmailContactDto> _emailContacts;
    private IList<TelephoneNumberDto> _telephoneNumbers;
    private IList<string> _chains;
    public EmailContactDto[] EmailContacts
    {
        get { return _emailContacts.ToArray(); }
        set { _emailContacts = value.ToList(); }
    }
    public TelephoneNumberDto[] TelephoneNumbers
    {
        get { return _telephoneNumbers.ToArray(); }
        set { _telephoneNumbers = value.ToList(); }
    }
    public string[] Chains
    {
        get { return _chains.ToArray(); }
        set { _chains = value.ToList(); }
    }
    //more properties
}

映射:

<class name="PartnerDto" table="[Partner]" schema-action="none" lazy="false" mutable="false">
<id name="Id">
  <generator class="hilo"/>
</id>
<bag name="Chains" table="PartnerChains" access="field.camelcase-underscore" lazy="false" fetch="subselect">
  <key column="PartnerId"/>
  <element column="Chain" type="System.String"/>
</bag>
<bag name="TelephoneNumbers" access="field.camelcase-underscore" lazy="false" fetch="subselect">
  <key column="PartnerId"/>
  <composite-element class="TelephoneNumberDto">
    <property name="Name" not-null="true"/>
    <property name="ClickToDial" not-null="true"/>
    <property name="SMS" not-null="true"/>
    <property name="Index" column="[Index]" not-null="true"/>
  </composite-element>
</bag>
<bag name="EmailContacts" access="field.camelcase-underscore" lazy="false" fetch="subselect">
  <key column="PartnerId"/>
  <composite-element class="EmailContactDto">
    <property name="Name" not-null="true"/>
    <property name="Email" not-null="true"/>
    <property name="NewsLetter" not-null="true"/>
    <property name="Index" column="[Index]" not-null="true"/>
  </composite-element>
</bag>
<!-- other properties -->

当我这样做时:

session.Query<PartnerDto>().Take(10);

我得到了正确的 10,但是我的 sql 显示它加载了 TelephoneNumber 表、EmailContact 表和 PartnerChains 表中的所有行,而不是将其限制为我正在加载的 10 个合作伙伴。

我错过了什么? (是的,我必须急切地加载所有内容 - 它们将在查询后立即序列化。)

编辑:找到解决方案:

我首先只查询分页查询的 ID,然后使用这些 ID 查询完整的对象图。由于前 10 个现在位于 where 子句中 - NHibernate 也使用它来过滤集合。是的,它并不完美 - 我总共有两次往返和五个查询,但目前仍然是我的最佳选择。

【问题讨论】:

    标签: c# nhibernate linq-to-nhibernate


    【解决方案1】:

    在您的收藏中使用batch-size,与您的页面大小相同,并删除lazy= "false"

    这将使用单个查询来获取每个集合类型。

    这是最简单的方法,也是最有效的方法之一。

    当然,在您序列化对象之前,会话必须保持打开状态。

    【讨论】:

    • 我会尝试看看这是否可行 - 但那会给我 4 次往返数据库 - 这是我试图避免的。
    • @Goblin:往返次数少不一定更好。
    • 虽然不是我的首选解决方案 - 这让我走上了正确的道路。非常感谢您的宝贵时间!
    【解决方案2】:

    我认为问题与 linqtoNH 无关,但由于您急切地检索集合这一事实而受到限制,这会导致单个查询的连接无法排名(“前 10”),因为有与来自数据库的原始结果集中的记录实体不再存在一对一的关系。

    【讨论】:

    • 上面的例子产生了 4 个不同的 sql,因此它具有执行“in”子句所需的数据,而不是选择所有内容。并且 sql 中没有连接。
    • @Goblin 是的,您有更多查询,但比一次下载完整结果集要轻。
    猜你喜欢
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 2013-02-17
    • 2011-08-24
    • 2014-04-19
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多