我有一个非常简单的主孩模型:
WorkflowEscalationPolicy< - WorkflowEscalation 即可。
可以从WorkflowEscalationPolicy.Escalations
属性访问WorkflowEscalations。
当我收到WorkflowEscalationPolicy
项时,我想急切地获取升级。
我有一个获取所有升级政策的方法。我试过用这个:
IEnumerable<IWorkflowEscalationPolicy> results =
Session
.Query<WorkflowEscalationPolicy>()
.Fetch(x=>x.Escalations)
.Where(q=>q.ApplicationKey==applicationKey);
和此:
IEnumerable<IWorkflowEscalationPolicy> results =
Session
.CreateCriteria<WorkflowEscalationPolicy>()
.SetFetchMode("Escalations", FetchMode.Eager)
.List<WorkflowEscalationPolicy>();
完成此任务,但两项工作都没有 - 因为子Escalations集合仍然是空的。我知道数据库中有WorkflowEscalations
。
我的映射文件:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="FB.SimpleWorkflow.NHibernate"
namespace="FB.SimpleWorkflow.NHibernate.Model" >
<class name="WorkflowEscalationPolicy" table="SW_WorkflowEscalationPolicy" >
<id name="Id">
<generator class="native" />
</id>
<property name="ApplicationKey" />
<property name="ActivityKey" />
<property name="InstanceKey" />
<property name="State" />
<property name="EscalateAfterSeconds" />
<property name="MaximumEscalationsPerTransition" />
<set name="Escalations" table="SW_WorkflowEscalation" cascade="all-delete-orphan" inverse="true">
<key column="WorkflowEscalationPolicyId" />
<one-to-many class="WorkflowEscalation" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="FB.SimpleWorkflow.NHibernate"
namespace="FB.SimpleWorkflow.NHibernate.Model" >
<class name="WorkflowEscalation" table="SW_WorkflowEscalation" >
<id name="Id">
<generator class="native" />
</id>
<property name="EscalatedTimeStamp" />
<property name="EscalatedByUserName" />
<property name="EscalatedOnHost" />
<many-to-one name="WorkflowEscalationPolicy" column="WorkflowEscalationPolicyID" />
<many-to-one name="WorkflowActivityInstanceTransition" column="WorkflowActivityInstanceTransitionId" />
</class>
</hibernate-mapping>
两者有什么区别,我在这里缺少什么?我认为在第一个例子中NHibernate引用了用于加载策略的映射文件?
NHibernate是v3.1
感谢@cremor进一步调查......
我已经分析了查询执行的生成的SQL,我得到了:
SELECT this_.Id as Id4_1_,
this_.ApplicationKey as Applicat2_4_1_,
this_.ActivityKey as Activity3_4_1_,
this_.InstanceKey as Instance4_4_1_,
this_.State as State4_1_,
this_.EscalateAfterSeconds as Escalate6_4_1_,
this_.MaximumEscalationsPerTransition as MaximumE7_4_1_,
escalation2_.WorkflowEscalationPolicyID as Workflow5_3_,
escalation2_.Id as Id3_,
escalation2_.Id as Id2_0_,
escalation2_.EscalatedTimeStamp as Escalate2_2_0_,
escalation2_.EscalatedByUserName as Escalate3_2_0_,
escalation2_.EscalatedOnHost as Escalate4_2_0_,
escalation2_.WorkflowEscalationPolicyID as Workflow5_2_0_,
escalation2_.WorkflowActivityInstanceTransitionID as Workflow6_2_0_
FROM SW_WorkflowEscalationPolicy this_
left outer join SW_WorkflowEscalation escalation2_ on this_.Id=escalation2_.WorkflowEscalationPolicyID
这就是我所期望的。
这将生成正确的SQL,并在主EscalationPolicy记录的右侧显示单个详细信息Escalation记录。因此,数据库很好,T-SQL很好,因此NHibernate内部存在误解。
答案 0 :(得分:0)
如果Escalations
集合是空的,那么它不应该没有急切加载的问题。因为如果你不急于加载一个集合,NHibernate会在你第一次访问它时加载它,所以你永远不会看到它是空的。唯一的区别是,eager加载在同一个SQL查询中加入集合,延迟加载执行一个(或许多,称为选择n + 1个问题)单独查询。
我不知道它在您使用的数据库中是否有所不同,但您的关键列在映射中有所不同,尽管它们应该相同(一个以大写“D”结尾,一个以小写结尾)。
您确定返回的WorkflowEscalationPolicy
对象不在任何NHibernate缓存中吗?如果是,NHibernate可能会丢弃SQL查询的结果,只返回现有对象。尝试为您的查询创建一个新会话。
PS:与您的问题无关,但在查询许多父对象时急切地加载集合时要小心。示例:如果您有100个父项,并且每个父项在集合中有100个元素,则SQL查询将返回10000行。您不会从NHinbernate获取10000个对象,但所有这些行仍然必须从数据库发送到您的客户端。在这种情况下更好地使用延迟加载,并使用subselect提取或批处理来映射集合,以防止选择n + 1问题。