简单的NHibernate渴望加载混乱

时间:2013-06-05 14:26:17

标签: nhibernate

我有一个非常简单的主孩模型:

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

更新:2013年6月6日

感谢@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内部存在误解。

1 个答案:

答案 0 :(得分:0)

如果Escalations集合是空的,那么它不应该没有急切加载的问题。因为如果你不急于加载一个集合,NHibernate会在你第一次访问它时加载它,所以你永远不会看到它是空的。唯一的区别是,eager加载在同一个SQL查询中加入集合,延迟加载执行一个(或许多,称为选择n + 1个问题)单独查询。

我不知道它在您使用的数据库中是否有所不同,但您的关键列在映射中有所不同,尽管它们应该相同(一个以大写“D”结尾,一个以小写结尾)。

您确定返回的WorkflowEscalationPolicy对象不在任何NHibernate缓存中吗?如果是,NHibernate可能会丢弃SQL查询的结果,只返回现有对象。尝试为您的查询创建一个新会话。

PS:与您的问题无关,但在查询许多父对象时急切地加载集合时要小心。示例:如果您有100个父项,并且每个父项在集合中有100个元素,则SQL查询将返回10000行。您不会从NHinbernate获取10000个对象,但所有这些行仍然必须从数据库发送到您的客户端。在这种情况下更好地使用延迟加载,并使用subselect提取或批处理来映射集合,以防止选择n + 1问题。