我有两个对象Case
和Note
。一个案例可以有成千上万的笔记,就像成千上万。我们试图以批量方式异步加载它们,并将它们流式传输到UI,这样就没有延迟等待它们全部加载。
类/映射是
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();
加载Case 123的前10个Notes,这个东西加载了Case对象,大约需要30秒,因为它上面有很多其他东西,加载时还有其他逻辑等等,我都不需要/想要在这个时候。我想要/需要的只是10个笔记。
我已尝试过这种映射的各种变体,但没有一种变得有效。我在这里做错了什么?
答案 0 :(得分:1)
您是如何使用此查询的?用户界面有什么用?喜欢在网格中显示什么?或者您是在组件中执行业务逻辑?
无论哪种方式,您都希望投射到另一个对象中。您的查询现在返回一个注释列表,然后按照映射加载该父对象。
因此,如果您使用此查询将信息发送到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();
这将使父对象无法加载。它还有一个额外的好处,即您只需要查询所需的信息,因为查询仅限于您预测的数据。
答案 1 :(得分:0)
重要的是要知道如果以上都是真的......
这是真正的映射(这不是一个明显的提取)
<class name="Note" table="CaseNotes">
<many-to-one name="Case" column="CaseID"/>
...
这是类(再次提取没有ID)
public class Note
{
public virtual Case Case {get; set;}
public virtual long CaseId {get; set;}
}
这将是一个加载笔记的UNIT TEST语句:
var list = NHibernateSession
.Query<Note>()
.Where(n => n.CaseId == 123)
.Skip(0).Take(10)
.ToList();
然后 NHibernate永远不会加载Case 对象。 <强>从不即可。这是因为:
原因是,加载相关引用(Case
属性)的触发器必须是明确的。
晴:
在某处使用了Case对象。 E.g。在覆盖
GetHashCode()
时使用Case.ID
或者:
有序列化或DTO转换,它触及Case属性
在这种情况下,NHibernate必须加载......
因此,使用基本查询创建一些单元测试,并确保您的实际上如上所示。然后它将按预期工作