views:

523

answers:

1

I have an entity "Group" with an assigned ID which is added to an aggregate in order to persist it. This causes an issue because NHibernate can't tell if it is new or existing. To remedy this issue, I changed the mapping to make the Group entity use optimistic locking on a sql timestamp version column. This caused a new issue. Group has a bag of sub objects. So when NHibernate flushes a new group to the database, it first creates the Group record in the Groups table, then inserts each of the sub objects, then does an update of the Group records to update the timestamp value. However, the sql that is generated to complete the update is invalid when the mapping is both dynamic-update="true" and optimistic-lock="version".

Here is the mapping:

<class xmlns="urn:nhibernate-mapping-2.2" dynamic-update="true" mutable="true" optimistic-lock="version" name="Group" table="Groups">
    <id name="GroupNumber" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="GroupNumber" length="5" />
      <generator class="assigned" />
    </id>
    <version generated="always" name="Timestamp" type="BinaryBlob" unsaved-value="null">
      <column name="TS" not-null="false" sql-type="timestamp" />
    </version>
    <property name="UID" update="false" type="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="GroupUID" unique="true" />
    </property>
    <property name="Description" type="AnsiString">
      <column name="GroupDescription" length="25" not-null="true" />
    </property>
    <bag access="field.camelcase-underscore" cascade="all" inverse="true" lazy="true" name="Assignments" mutable="true" order-by="GroupAssignAssignment">
      <key foreign-key="fk_Group_Assignments">
        <column name="GroupNumber" />
      </key>
      <one-to-many class="Assignment" />
    </bag>
    <many-to-one class="Aggregate" name="Aggregate">
      <column name="GroupParentID" not-null="true" />
    </many-to-one>
  </class>
</hibernate-mapping> 

When the mapping includes both the dynamic update and the optimistic lock, the sql generated is:

UPDATE groups SET WHERE GroupNumber = 11111 AND TS=0x00000007877

This is obviously invalid as there are no SET statements. If I remove the dynamic update part, everything gets updated during this update statement instead. This makes the statement valid, but rather unnecessary.

Has anyone seen this issue before? Am I missing something?

Thanks, Steve

A: 

Try setting the unsaved-value attribute in the id element; this should allow NHibernate to distinguish between new and existing records and sidestep the timestamp problem.

<id name="GroupNumber" unsaved-value="" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

The documentation leads me to believe that this should default to empty string but it's worth a try.

Jamie Ide
That didn't seem to make a difference in the query generated.
SteveBering