After much toil, I've narrowed down my problem to the following:
Code:
public class Customer {
int customerId;
Region region;
DateTime version;
//getters/setters...
}
public class Region {
int regionId;
Agency agency;
DateTime version;
//getters/setters...
}
public class Agency {
int agencyId;
DateTime version;
}
Here are the stripped mapping files:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" default-access="field">
<class name="SpringAir.Objects.Customer, SpringAir.Objects" table="Customer">
<id name="customerId" column="CustomerId" unsaved-value="-1">
<generator class="assigned" />
</id>
<timestamp name="version" column="Version" />
<many-to-one name="region" column="RegionId" not-null="true" />
</class>
<class name="SpringAir.Objects.Region, SpringAir.Objects" table="Region">
<id name="regionId" column="RegionId" type="Int32" access="field" unsaved-value="-1">
<generator class="identity" />
</id>
<timestamp name="version" column="Version" />
<many-to-one name="agency" column="AgencyId" not-null="true" />
</class>
<class name="SpringAir.Objects.Agency, SpringAir.Objects" table="Agency">
<id name="agencyId" column="AgencyId" type="Int32" access="field" unsaved-value="-1">
<generator class="assigned" />
</id>
<timestamp name="version" column="Version" />
</class>
</hibernate-mapping>
Here is what I'm doing:
- Entering page, loading the Customer via the ISession
- Loading a list of all Regions, and selecting the entry that corresponds to the Region that the Customer is currently assigned to
- Disconnecting the ISession, then serializing it to the ASP.NET state server (at this point, page is rendered)
- I then click the "Save" button (not making any changes to the data); the Save event deserializes the ISession, calls SaveOrUpdate on the Customer instance in an ITransaction; this fails with "Row was updated or deleted by another transaction for SpringAir.Objects.Agency instance with identifier: 56"
Additional info:
- The only other object which might be loaded is the User object, which contains no reference to Region, Agency, or Customer.
- Commenting out the many-to-one reference to the Agency in the Region mapping resolves this issue.
Given my understanding of NHibernate, this should work, should it not? I have absolutely no idea what to do from here; I don't understand why any of the loaded Regions or Agency objects would be considered dirty since literally nothing was done to/with them. Any help is much appreciated.
The log states the following:
Quote:
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - reconnecting session
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - loading [User#103]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - attempting to resolve [User#103]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - resolved object in session cache [SpringAir.Objects.User#103]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - loading [Customer#469]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - attempting to resolve [Customer#469]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - resolved object in session cache [SpringAir.Objects.Customer#469]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - SaveOrUpdate() persistent instance
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - flushing session
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - Flushing entities and processing referenced collections
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - Updating entity: [SpringAir.Objects.Agency#56]
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - Processing unreferenced collections
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - scheduling collection removes/(re)creates/updates
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - Flushed: 0 insertions, 1 updates, 0 deletions to 106 objects
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
DEBUG 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - executing flush
ERROR 2005-10-19 12:33:56,187 [3412] NHibernate.StaleObjectStateException - An operation failed due to stale data
NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction for SpringAir.Objects.Agency instance with identifier: 56
ERROR 2005-10-19 12:33:56,187 [3412] NHibernate.Impl.SessionImpl - could not synchronize database state with session
NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction for SpringAir.Objects.Agency instance with identifier: 56
at NHibernate.Persister.AbstractEntityPersister.Check(Int32 rows, Object id)
at NHibernate.Persister.EntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Boolean[] includeProperty, Object oldVersion, Object obj, SqlString sqlUpdateString, ISessionImplementor session)
at NHibernate.Persister.EntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Object[] oldFields, Object oldVersion, Object obj, ISessionImplementor session)
at NHibernate.Impl.ScheduledUpdate.Execute()
at NHibernate.Impl.SessionImpl.Execute(IExecutable executable)
at NHibernate.Impl.SessionImpl.ExecuteAll(IList list)
at NHibernate.Impl.SessionImpl.Execute()
So for some reason, the Agency is marked as dirty. Hmmm... it seems omitting the 'version' definition in the Agency mapping file fixes the problem as well. Could it be that the some data int the serialized/deserialized DateTime value is being lost somehow?