渴望在Future和HQL的帮助下加载子集合

时间:2011-12-15 15:58:28

标签: c# nhibernate hql eager-loading

我正在尝试加载我正在选择的实体的子项的子集合。我试图模仿this way这样做,基本上创建两个未来的查询,然后枚举其中一个。这应该导致对数据库的两个查询:

var idd = session.CreateQuery("from ItemDeliveryDetail idd " + 
                              "join fetch idd.ItemDelivery " +
                              "left join fetch idd.SupplierInvoice " +
                              "where idd.Id = 21931828")
                 .Future<ItemDeliveryDetail>();

var spc = session.CreateQuery("from SpecialCondition spc " +
                              "where spc.ItemDelivery " +
                              "in (select idd.ItemDelivery " +
                                  "from ItemDeliveryDetail idd " +
                                  "where idd.Id = 21931828)")
                 .Future<SpecialCondition>();

var result = idd.ToList();

最后一行确实导致对数据库的两次查询。查询正是我的期望(它们相当冗长,我认为它们与问题无关,但如果你想看到它们,我会粘贴它们here)。

问题是,这两个查询的结果没有合并,即以下枚举仍然会在数据库中查询每个SpecialCondition的{​​{1}}:

ItemDelivery

如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

快速获胜可能是将batch-size=50添加到ItemDeliverySpecialConditions之间的行李映射中。

但是我建议你阅读Ayende的这篇博客“Eagerly loading entity associations efficiently with NHibernate”,因为它可能会为你提供你想要的答案。

这里面临着经典的选择n + 1问题。我宁愿有1次或者2次多次访问数据库,而不是一个大的cartesian product结果集。我相信这将是最高效的路线。

答案 1 :(得分:1)

您的第二个查询加载ItemDelivery.SpecialConditions个收藏集;只有一个未使用的SpecialConditions列表。

我同意Rippo的看法,使用batch-size通常更干净,性能更高,即使它会导致一两次往返

那就是说,你的第二个问题应该是:

var spc = session.CreateQuery("from ItemDelivery id " +
                              "join fetch id.SpecialCondition "
                              "where id in (select idd.ItemDelivery " +
                                           "from ItemDeliveryDetail idd " +
                                           "where idd.Id = 21931828)"
             .Future<ItemDelivery>();

答案 2 :(得分:0)

您需要使用两次相同的基本查询,我认为这是您的问题。

var idd = session.CreateQuery("from ItemDeliveryDetail idd " + 
                          "join fetch idd.ItemDelivery " +
                          "left join fetch idd.SupplierInvoice " +
                          "where idd.Id = 21931828")
             .Future<ItemDeliveryDetail>();

var spc = session.CreateQuery("from ItemDeliveryDetail idd " + 
                          "join fetch idd.ItemDelivery id " +
                          "join fetch id.SpecialCondition spc " +
                         "where idd.Id = 21931828")
             .Future<ItemDeliveryDetail>();

var result = idd.ToList();

是的我意识到这可能会为您带来笛卡尔产品,但我使用这种技术取得了很好的成功。