【问题标题】:Help mapping a bag with NHibernate, items in bag not saving帮助使用 NHibernate 映射包,包中的项目未保存
【发布时间】:2011-09-13 14:46:24
【问题描述】:

我在获取存储在另一个类中的一个类的列表时遇到了一些问题。

我有一个类交集,它是一个包含区域列表的基本类型设备,这是我的另一个类。每个路口可以有多个区域,但只能将 1 个路口分配给特定区域。

我的设备/交叉点映射如下:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Devices.Device, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Device`" lazy="false">
<id name="PK" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="PK" />
  <generator class="identity" />
</id>
<many-to-one class="EMTRAC.Connections.Connection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="LocalConnection" lazy="false" cascade="all">
  <column name="LocalConnection_id" />
</many-to-one>
<many-to-one class="EMTRAC.Connections.Connection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Connection" lazy="false" cascade="all">
  <column name="Connection_id" />
</many-to-one>
<many-to-one class="EMTRAC.Packets.Packet, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Configuration" lazy="false" cascade="all">
  <column name="Configuration_id" />
</many-to-one>
<joined-subclass name="EMTRAC.Intersections.Intersection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" lazy="false">
  <key>
    <column name="Device_id" />
  </key>
  <bag name="Zones" cascade="all-delete-orphan">
    <key>
      <column name="Intersection_id" />
    </key>
    <one-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </bag>
  <many-to-one class="EMTRAC.Intersections.Streets, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Streets" lazy="false" cascade="all">
    <column name="Streets_id" />
  </many-to-one>
  <many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Position" lazy="false" cascade="all">
    <column name="Position" />
  </many-to-one>
</joined-subclass>

我对 Zone 类的映射如下:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Zone`" lazy="false">
<id name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="PK" />
  <generator class="identity" />
</id>
<property name="Active" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="Active" />
</property>
<property name="Dir" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="Dir" />
</property>
<property name="IntID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="IntID" />
</property>
<property name="Width" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="Width" />
</property>
<many-to-one class="EMTRAC.Headings.Heading, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Heading" cascade="all">
  <column name="Heading_id" />
</many-to-one>
<many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Start" cascade="all">
  <column name="Start_id" />
</many-to-one>
<many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Finish" cascade="all">
  <column name="Finish_id" />
</many-to-one>

现在,如果我创建一个 Zone 对象并将其保存到数据库中,则一切都保存得很好,并且引用 Intersection 对象的 Intersection_Id 字段如预期的那样为 null。但是,一旦我将此 Zone 对象添加到 Intersection 并保存 Intersection,它就不会通过 Intersection_id 字段将 Zone 链接到 Intersection,并且加载 Intersection 不会包含 Zones List 中的任何区域。

如果我在没有先保存区域的情况下保存了交叉点,则交叉点可以正常保存,但不会保存区域。

查看 session.Save(intersection) 的 SQL,我没有看到任何发送来尝试保存区域的内容。

另外,如果我保存交叉点,然后尝试

foreach(Zone z in intersection.Zones) session.Save(z);

NHibernate 不执行任何 SQL 也不保存区域。

这可能是我缺少的一些小东西。有什么想法吗?

编辑

我实际上找到了解决方案。这些映射实际上是正确的,或者至少我假设它们是正确的,因为它们看起来并没有明显的错误,尽管我对 NHibernate 的了解还不够,无法确定该解决方案为何有效。

无论如何,解决方案是三倍的。

首先,我必须确保在保存交叉点与包含该区域的列表之前已保存该区域。如果在调用 Flush 时不保存 Zone,如下所述,当它尝试将 Zone 链接到 Intersection 但未在 Zones 的表中找到 Zone 记录时,会出现错误。

这是通过调用 Session.Save(zone) 来完成的,其中 Session 是一个 ISession。

Zone 保存后,我使用上述方法保存了 Intersection,但调用了 Session.Save(intersection)。

解决问题的最后一点是在我保存交叉路口后,我必须为 ISession 调用 Session.Flush(),然后将区域链接到交叉路口。

这解决了问题,现在所有内容都已正确保存、加载和链接。

ISession.Flush() 在后台做了什么,需要我调用它来将所有东西拼凑在一起,为什么它没有全部保存,只是调用 Session.Save(intersection) 并为包设置了级联集是问题?

【问题讨论】:

  • 映射似乎很好。有什么例外吗?
  • 不,当我保存交叉点时,它只是没有将交叉点引用到区域,如果我不先保存区域,则区域根本不会保存到区域表.
  • 查看我调用 session.Save(intersection) 时正在执行的 SQL,NHibernate 根本没有尝试保存或更改区域。有什么想法吗?
  • 另外,如果我保存交集,然后尝试 foreach(Zone z in intersection.Zones) 会话。Save(z) 不执行任何 SQL 并且不保存该区域。

标签: nhibernate nhibernate-mapping


【解决方案1】:

在 NH 中,更新和插入通常在 Session.Flush() 上进行批处理和执行,但由于您使用的是 identity,NH 必须立即发出 INSERT 以生成 id,但对更新进行批处理。为了提高性能和启用批处理,还有其他密钥生成策略(GUID、HiLo、...)。

根本没有插入区域inverse 可能会有所帮助

<bag name="Zones" cascade="all-delete-orphan" inverse="true">

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多