NHIbernate 延迟加载一个父对象
NHIbernate lazy load a parent object
我有两个对象,Case
和 Note
。一个 Case 可以有成百上千的 Notes。我们正在尝试异步、分批加载它们,并将它们流式传输到 UI,这样就不会延迟等待它们全部加载。
class/mappings是
public class Case
{
public virtual IList<Note> Notes { get; protected set; }
}
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SCMS.TAMS.BusinessEntities" namespace="SCMS.TAMS.BusinessEntities">
<class name="Case" table="Cases">
<bag name="Notes" inverse="true" cascade="all" lazy="true">
<key column="CaseID" />
<one-to-many class="Note" />
</bag>
</class>
</hibernate-mapping>
public class Note
{
public virtual Case Case {get; set;}
public virtual long CaseId {get; set;}
}
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SCMS.TAMS.BusinessEntities" namespace="SCMS.TAMS.BusinessEntities" default-lazy="true">
<class name="Note" table="CaseNotes">
<many-to-one name="Case" column="CaseID"/>
<property name="CaseId" column="CaseID" />
</class>
</hibernate-mapping>
现在,当我打电话时
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Skip(0).Take(10).ToList();
加载案例 123 的前 10 个注释,加载案例对象,这需要大约 30 秒,因为上面还有很多其他东西,加载时还有其他逻辑,等等,none 其中我 need/want 此时。我want/need都是10个音符
我尝试了此映射的各种变体,其中 none 已经奏效。我在这里做错了什么?
您如何使用此查询?是 UI 的东西吗?喜欢在网格中显示还是什么?还是在组件中执行业务逻辑?
你想投影到另一个对象的任何一种方式。您现在的查询 returns 一个注释列表,然后将根据映射加载该父对象。
因此,如果您使用此查询将信息发送到 asp.net mvc 应用程序的 UI,请直接投影到您的视图模型中
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Select(n => new SomeViewModel { Prop1 = n.Prop1, Prop2 = n.Prop2 ...}).Skip(0).Take(10).ToList();
或者创建一个匿名对象
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Select n => new { n.Prop1, n.Prop2, ...}).Skip(0).Take(10).ToList();
这将阻止加载父对象。它还具有额外的好处,即您只查询所需的信息,因为查询仅限于您正在投影的数据。
重要的是要知道如果以上都是真的...
这是真正的映射(这不是它只是一个明显的摘录)
<class name="Note" table="CaseNotes">
<many-to-one name="Case" column="CaseID"/>
...
这是class(再次提取无ID)
public class Note
{
public virtual Case Case {get; set;}
public virtual long CaseId {get; set;}
}
这将是一个用于加载注释的单元测试语句:
var list = NHibernateSession
.Query<Note>()
.Where(n => n.CaseId == 123)
.Skip(0).Take(10)
.ToList();
然后 NHibernate 将永远不会加载 Case 对象。 从不。因为:
NHibernate is lazy, just live with it
原因,加载相关引用的触发器 (Case
属性) 必须是明确的。
主要是:
there is usage of the Case object somewhere. E.g. in override of the GetHashCode()
the Case.ID is used
或者:
there is a serialization or DTO conversion which does touch the Case property
在那种情况下,NHibernate 必须加载...
因此,使用基本查询创建一些单元测试并确保您的确实如上所示。然后它将按预期工作
我有两个对象,Case
和 Note
。一个 Case 可以有成百上千的 Notes。我们正在尝试异步、分批加载它们,并将它们流式传输到 UI,这样就不会延迟等待它们全部加载。
class/mappings是
public class Case
{
public virtual IList<Note> Notes { get; protected set; }
}
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SCMS.TAMS.BusinessEntities" namespace="SCMS.TAMS.BusinessEntities">
<class name="Case" table="Cases">
<bag name="Notes" inverse="true" cascade="all" lazy="true">
<key column="CaseID" />
<one-to-many class="Note" />
</bag>
</class>
</hibernate-mapping>
public class Note
{
public virtual Case Case {get; set;}
public virtual long CaseId {get; set;}
}
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SCMS.TAMS.BusinessEntities" namespace="SCMS.TAMS.BusinessEntities" default-lazy="true">
<class name="Note" table="CaseNotes">
<many-to-one name="Case" column="CaseID"/>
<property name="CaseId" column="CaseID" />
</class>
</hibernate-mapping>
现在,当我打电话时
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Skip(0).Take(10).ToList();
加载案例 123 的前 10 个注释,加载案例对象,这需要大约 30 秒,因为上面还有很多其他东西,加载时还有其他逻辑,等等,none 其中我 need/want 此时。我want/need都是10个音符
我尝试了此映射的各种变体,其中 none 已经奏效。我在这里做错了什么?
您如何使用此查询?是 UI 的东西吗?喜欢在网格中显示还是什么?还是在组件中执行业务逻辑?
你想投影到另一个对象的任何一种方式。您现在的查询 returns 一个注释列表,然后将根据映射加载该父对象。
因此,如果您使用此查询将信息发送到 asp.net mvc 应用程序的 UI,请直接投影到您的视图模型中
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Select(n => new SomeViewModel { Prop1 = n.Prop1, Prop2 = n.Prop2 ...}).Skip(0).Take(10).ToList();
或者创建一个匿名对象
NHibernateSession.Query<Note>().Where(n => n.CaseId == 123).Select n => new { n.Prop1, n.Prop2, ...}).Skip(0).Take(10).ToList();
这将阻止加载父对象。它还具有额外的好处,即您只查询所需的信息,因为查询仅限于您正在投影的数据。
重要的是要知道如果以上都是真的...
这是真正的映射(这不是它只是一个明显的摘录)
<class name="Note" table="CaseNotes">
<many-to-one name="Case" column="CaseID"/>
...
这是class(再次提取无ID)
public class Note
{
public virtual Case Case {get; set;}
public virtual long CaseId {get; set;}
}
这将是一个用于加载注释的单元测试语句:
var list = NHibernateSession
.Query<Note>()
.Where(n => n.CaseId == 123)
.Skip(0).Take(10)
.ToList();
然后 NHibernate 将永远不会加载 Case 对象。 从不。因为:
NHibernate is lazy, just live with it
原因,加载相关引用的触发器 (Case
属性) 必须是明确的。
主要是:
there is usage of the Case object somewhere. E.g. in override of the
GetHashCode()
the Case.ID is used
或者:
there is a serialization or DTO conversion which does touch the Case property
在那种情况下,NHibernate 必须加载...
因此,使用基本查询创建一些单元测试并确保您的确实如上所示。然后它将按预期工作