NHibernate父集合、子集合和未来集合

NHibernate父集合、子集合和未来集合,nhibernate,future,Nhibernate,Future,我有这样一个设置:Parent,有一个Child集合 class Parent { IList<Child> Childs { get; set; } } 这就产生了经典的N+1问题。两条SQL语句在一次往返中发送到服务器,所以所有数据都存在于一级缓存中,那么为什么NH仍然为每个子级都存在SQL 版本3.1.0.400执行未来查询时,将所有父对象和子对象拉入一级缓存。父对象包含需要填充的惰性集合。要填充集合,NHibernate必须查询数据库。(稍后我们将了解原因。)查询返

我有这样一个设置:Parent,有一个Child集合

class Parent {
    IList<Child> Childs { get; set; }
}
这就产生了经典的N+1问题。两条SQL语句在一次往返中发送到服务器,所以所有数据都存在于一级缓存中,那么为什么NH仍然为每个子级都存在SQL


版本3.1.0.400

执行未来查询时,将所有父对象和子对象拉入一级缓存。父对象包含需要填充的惰性集合。要填充集合,NHibernate必须查询数据库。(稍后我们将了解原因。)查询返回子对象,并且这些子对象已经在一级缓存中。因此,这些对象用于填充集合

现在为什么NHibernate必须查询数据库来填充Childs集合?您可以在集合上有一个“where”子句,它过滤掉IsDeleted==true的子对象。您可以在EventListener中使用代码来过滤某些子对象。基本上,会发生很多事情,NHibernate不能对父对象和子对象之间的关系做出任何假设

通过在HQL或映射中指定抓取策略,可以为它提供足够的信息。在HQL中,您可以编写:

var parents = session.CreateQuery("from Parent p join fetch p.Childs").Future<Parent>();
var parents=session.CreateQuery(“从父级p join fetch p.Childs”).Future();
使用future的子对象查询是完全可选的,因为您要获取父对象的子对象。由于join-fetch,您将获得重复的父对象,尽管它们是相同的对象。(您正在数据库中进行内部联接,并为每个子行返回父行的一个副本。)您可以通过迭代parents.Distinct()来消除这些

如果您总是希望获取具有相应父对象的子对象,还可以在父映射中使用fetch=“join”

<bag name="Children" cascade="all-delete-orphan" fetch="join">
  <key column="ParentId"/>
  <one-to-many class="Child"/>
</bag>

如果这两个选项都不适用于您的场景,则可以在集合映射上指定批大小。当您点击parent.Childs时,仍然会执行数据库查询,但NHibernate会急切地初始化任何其他集合代理

<bag name="Children" cascade="all-delete-orphan" batch-size="10">
  <key column="ParentId"/>
  <one-to-many class="Child"/>
</bag>

执行未来查询时,将所有父对象和子对象拉入一级缓存。父对象包含需要填充的惰性集合。要填充集合,NHibernate必须查询数据库。(稍后我们将了解原因。)查询返回子对象,并且这些子对象已经在一级缓存中。因此,这些对象用于填充集合

现在为什么NHibernate必须查询数据库来填充Childs集合?您可以在集合上有一个“where”子句,它过滤掉IsDeleted==true的子对象。您可以在EventListener中使用代码来过滤某些子对象。基本上,会发生很多事情,NHibernate不能对父对象和子对象之间的关系做出任何假设

通过在HQL或映射中指定抓取策略,可以为它提供足够的信息。在HQL中,您可以编写:

var parents = session.CreateQuery("from Parent p join fetch p.Childs").Future<Parent>();
var parents=session.CreateQuery(“从父级p join fetch p.Childs”).Future();
使用future的子对象查询是完全可选的,因为您要获取父对象的子对象。由于join-fetch,您将获得重复的父对象,尽管它们是相同的对象。(您正在数据库中进行内部联接,并为每个子行返回父行的一个副本。)您可以通过迭代parents.Distinct()来消除这些

如果您总是希望获取具有相应父对象的子对象,还可以在父映射中使用fetch=“join”

<bag name="Children" cascade="all-delete-orphan" fetch="join">
  <key column="ParentId"/>
  <one-to-many class="Child"/>
</bag>

如果这两个选项都不适用于您的场景,则可以在集合映射上指定批大小。当您点击parent.Childs时,仍然会执行数据库查询,但NHibernate会急切地初始化任何其他集合代理

<bag name="Children" cascade="all-delete-orphan" batch-size="10">
  <key column="ParentId"/>
  <one-to-many class="Child"/>
</bag>