Nhibernate:readonly属性导致急切负载

时间:2013-09-12 12:03:26

标签: nhibernate

我们最近升级到最新版本的NHibernate(3.3.3.4001),我遇到了NHibernate 2.1.2.4000中不存在的问题。这让我相信它可能是新内置字节码提供程序的问题。

考虑以下映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Foo.Core.Domain" assembly="Foo.Core" default-access="property">
  <class name="EntityA" table="EntityA" lazy="true">

    <id name="Id" column="EntityAId">
      <generator class="native" />
    </id>

    <many-to-one name="EntityB" column="EntityBId" class="EntityB" not-null="true" />
    <many-to-one name="EntityC" column="EntityCId" class="EntityC" not-null="true" access="readonly" insert="true" update="false" />


  </class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Foo.Core.Domain" assembly="Foo.Core" default-access="property">
  <class name="EntityB" table="EntityB" lazy="true">

    <id name="Id" column="EntityBId">
      <generator class="native" />
    </id>

    <many-to-one name="EntityC" column="EntityCId" class="EntityC" not-null="true"  />

  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Foo.Core.Domain" assembly="Foo.Core" default-access="property">
  <class name="EntityC" table="EntityC" lazy="true">

    <id name="Id" column="EntityCId">
      <generator class="native" />
    </id>


  </class>
</hibernate-mapping>

这是我对EntityA的类定义:

Public Class EntityA

    Public Overridable Property Id As Integer

    Public Overridable Property EntityB As EntityB

    Public Overridable ReadOnly Property EntityC As EntityC
        Get
           Return If(EntityB IsNot Nothing, EntityB.EntityC, Nothing)
        End Get
    End Property


End Class

当我为一个EntityA实例调用Session.Get时会出现问题 - 它会立即导致为其相应的EntityB发出一个select:

Session.Get(Of EntityA)(id) ' Causes the EntityB that EntityA references to be loaded as well.

我最好的猜测是,在构建代理时,字节码提供程序会导致我的readonly“EntityC”属性被评估,这会强制引用EntityB的负载。

有没有办法避免使用NHibernate 3.3.3这种类型的模型产生急切的负载?

1 个答案:

答案 0 :(得分:1)

我使用此类层次结构和NH 3.3.3 SP1上的映射进行了一些测试,这是我的观察结果:

  • 使用session.Get<>加载EntityA,然后对该对象执行某些操作 没有触及属性EntityB,EntityC,EntityB会 没有加载。触摸任一属性都会触发查询 当然,这是正常的。

  • 加载EntityA,更新与属性无关的内容 EntityB和EntityC就像更改EntityA名称一样,然后回滚 交易,没有发出额外的SELECT。

  • 加载EntityA,什么也不做,然后提交事务,第二个SELECT 已发布EntityB。

  • 加载EntityA,对会话进行一些查询,然后是所说的SELECT 已发布EntityB。

所有测试均在FlushMode.Auto。

下完成

通过这些,我得出的结论是NHibernate在这种情况下的行为是完全可以预期的:当进行刷新时,NH需要检查对象的肮脏,它需要获取属性EntityC的值以与之前的值进行比较,这就是触发SELECT问题的原因。

绝对不是因为session.Get<>或新代理。您可以轻松地进行更多测试来证明这一点。我不明白为什么NH 2.1.2会有所不同。

我也尝试过NH 3.3.1的测试,响应与NH 3.3.3 SP1完全相同。