【问题标题】:nHibernate - eager fetching a list with child lists already populatednHibernate - 急切地获取已填充子列表的列表
【发布时间】:2011-02-18 14:54:24
【问题描述】:

我有一些物品:

Public Class Person() {
    public int Id {get;set;}
    public IList<Account> Accounts {get;set;}
    public string Email {get; set;}
}

public class Account(){
    public int Id {get;set;}
    public IList<AccountPayment> Payments {get;set;}
    public IList<Venue> Venues {get;set;}
}

public class AccountPayment(){
    public int Id {get;set;}
    public DateTime PaymentDate {get;set;}
    public decimal PaymentAmount {get;set;}
}

public class Venue(){
    public int Id {get;set;}
    public string AddressLine1 {get;set;}
    public string Postcode {get;set;}
}

这些类通过 nHibernate 映射到 MS Sql - 每个类在 db 中有一个表...

我想在我的存储库中创建一个方法 GetAccounts(int PersonID),它将返回一个列表,其中包含以最有效的方式填充的所有帐户的子集合。谁能给我有关如何执行此操作的任何指示 - 如果我能提供帮助,我真的不想在我的映射中将列表设置为子选择...

谢谢。

【问题讨论】:

  • 这篇博文解释了一种有效的方法:ayende.com/Blog/archive/2010/01/16/…
  • 嗨 Diego,问题是我正在尝试加载子集合,即 Person 对象的 Account 属性 - 我之前在尝试执行此操作时查看了这篇文章,并进行了第二次调查,我仍然看不到这样做的方法。我错过了什么吗?
  • 此链接不再有效,不幸的是,答案不包含其中的任何相关信息。
  • @Aaronaught,链接工作正常,尽管它现在重定向到 ayende.com/blog/4367/…
  • 昨晚我点击它时没有工作。事实仍然是naked links are not good answers.

标签: nhibernate eager-loading


【解决方案1】:

如果您按照您提到的方式将类映射到表,为什么不直接调用 Person 对象来获取他们的所有帐户?当您从存储库中调用 Person 对象时,您可以预先加载 Accounts。像这样:

 public Person GetById(int id)
    {
        using (var tx = _sessionBuilder.GetSession().BeginTransaction())
        {
            // -- Lazy load way --
            //Person person = _sessionBuilder.GetSession().Get<Person>(id);
            //tx.Commit();
            //return person;

            // -- Eager load way --                
            Person person = _sessionBuilder.GetSession().CreateCriteria<Person>()
                   .Add(Restrictions.IdEq(id))
                   .SetFetchMode("Accounts", FetchMode.Eager)
                   .UniqueResult<Person>();
            tx.Commit();
            return person;
        }
    }

【讨论】:

  • 理想情况下,我也想在个人对象(帐户支付和地点)的 Accounts 属性上急切加载集合。我不认为上面可以做到这一点?
  • SetFetchMode 用于集合(尤其是当有多个集合时)在性能方面不是一个好主意。
  • @Paul - 我不确定 FetchMode.Eager 是否会进行嵌套集合。您可以使用 NHProf 查看 SQL。急切加载的另一种方法可能是在原始语句中调用您的存储库并急切地调用 Payments 和 Venues。 .... .SetFetchMode("Payments", FetchMode.Eager) .SetFetchMode("Venues", FetchMode.Eager) ....
  • @Diego - 性能是我最不担心的事情。 :)。我不确定 Paul 的域集是返回 50 条记录还是 500 万条记录。我也渴望听到其他解决方案。我提出的解决方案适用于我和我从事的应用程序。
  • 嗨,我正在使用 NHProf... 非常棒。不幸的是 FetchMode.Eager 没有得到想要的结果——我得到了一个巨大的笛卡尔积......开始认为这可能无法完成。烦人的事情是,如果我在映射上设置 Fetch.Subselect(),它会做我想要的。
【解决方案2】:

好的,在尝试了很多不同的方法之后,我最终发现这个问题中对我来说最有效的解决方案:

Eager loading child collection with NHibernate

我上面的问题是我遇到的实际挑战的一个大大简化的版本,但是使用上述方法设法将 db hits 降低到 2...与我最初的实现相比有了巨大的改进。

感谢你们的帮助和指点。一路上学到了一点...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2017-04-18
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多