0

I have a very simple master-child model:

WorkflowEscalationPolicy<--WorkflowEscalation.

The WorkflowEscalations are accessible from the WorkflowEscalationPolicy.Escalations property.

I want to eagerly fetch the escalations when I get the WorkflowEscalationPolicy items.

I have a method that gets all escalation policies. I have tried using this:

IEnumerable<IWorkflowEscalationPolicy> results = 
  Session
 .Query<WorkflowEscalationPolicy>()
 .Fetch(x=>x.Escalations)
 .Where(q=>q.ApplicationKey==applicationKey);

and this:

IEnumerable<IWorkflowEscalationPolicy> results = 
 Session
 .CreateCriteria<WorkflowEscalationPolicy>()
 .SetFetchMode("Escalations", FetchMode.Eager)
 .List<WorkflowEscalationPolicy>();

to accomplish this, but neither work - in that the child Escalations collection remains empty. I know that there are WorkflowEscalations in the database.

My mapping files:

<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>

What is the difference between the two and what am I missing here? I thought that in the first instance NHibernate refers to the mapping files for loading strategies?

NHibernate is v3.1

Update: 6 June 2013

Further investigations thanks to @cremor ...

I've profiled the generated SQL that the query executes and I get:

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

Which is what I would expect.

This generates the correct SQL, with the single detail Escalation record to the right of the master EscalationPolicy record. Therefore, the database is fine, the T-SQL is fine and therefore there is a misunderstanding within the NHibernate somewhere.

4

1 回答 1

0

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

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

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

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

于 2013-06-06T07:03:42.647 回答