I'm upgrading an old NHibernate 1.2 solution I've taken over to NHib 3.1. We're having problems with persisting a parent child relationship. Which gives us this error:
NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
This code was working in NHib 1.2 but does not work in 3.1
We're saving much like this code below:
Film f = NewFilm();
Recipe r = new Recipe("2", TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15));
f.Recipe = r;
SaveAndFlush(f, r); //custom code that saves f then saves r then flushes through the session.
However if we save r then f and flush it works.
I'd like to know why this happens, why the change between NHib versions. Is it the way the sesison thinks entities are transient now? Does it handle the foreign key id generator differently?
On a side note, the ID of the recipe doesn't equal the ID of the film, which I would expect it to do.
HMB files. - UPDATED to include full files
Film:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo">
<subclass name="Application.Core.Domain.Film, Application.Core" extends="Application.Core.Domain.VideoContent, Application.Core" discriminator-value="film" lazy="true">
<list inverse="false" lazy="true" name="Resources" access="field.camelcase-underscore" cascade="all-delete-orphan">
<key column="FilmId" />
<index column="PositionInFilm"/>
<one-to-many class="Application.Core.Domain.ContentResource, Application.Core" />
</list>
<list inverse="false" lazy="true" name="Steps" access="field.camelcase-underscore" cascade="all-delete-orphan">
<key column="FilmId" />
<index column="PositionInWebText"/>
<one-to-many class="Application.Core.Domain.WebText, Application.Core" />
</list>
<property name="FilmType" column="FilmType" />
<property name="PosterFrameTimeCode" column="PosterFrameTimeCode" />
<one-to-one name="Recipe" class="Application.Core.Domain.Recipe, Application.Core" cascade="save-update" access="field.camelcase-underscore"/>
<bag lazy="true" name="Shapes" access="field.camelcase-underscore" cascade="save-update" where="Archived=0">
<key column="ContentId"/>
<one-to-many class="Application.Core.Domain.FilmShape, Application.Core"/>
</bag>
<bag lazy="true" name="ArchivedShapes" access="field.camelcase-underscore" cascade="save-update" where="Archived=1">
<key column="ContentId"/>
<one-to-many class="Application.Core.Domain.FilmShape, Application.Core" />
</bag>
<many-to-one name="FilmToReplace" column="ReplacesFilmId" class="Application.Core.Domain.Film, Application.Core" access="field.camelcase-underscore" />
</subclass>
Recipe:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo">
<class name="Application.Core.Domain.Recipe,Application.Core" table="tbl_Recipe" lazy="false">
<id name="Id" column="HeaderId" type="System.Guid" access="field.camelcase-underscore">
<generator class="foreign">
<param name="property">Content</param>
</generator>
</id>
<list inverse="false" lazy="true" name="RecipeIngredients" access="field.camelcase-underscore" cascade="all-delete-orphan">
<key column="RecipeId" />
<index column="PositionInRecipe"/>
<one-to-many class="Application.Core.Domain.RecipeIngredient, Application.Core" />
</list>
<property name="Serves" column="Serves" type="System.String"/>
<property name="PreparationTime" column="PreparationTime" type="TimeSpan"/>
<property name="CookingTime" column="CookingTime" type="TimeSpan"/>
<property name="OvenTemperature" column="OvenTemperature" type="Application.Data.UserTypes.TemperatureType, Application.Data"/>
<one-to-one name="Content" class="Application.Core.Domain.Content, Application.Core" constrained="true" access="field.camelcase-underscore"/>
</class>
</hibernate-mapping>
On a side note, the ID of the recipe doesn't equal the ID of the film, which I would expect it to do.
For ID equality you should use generator class="foreign" – jjjjj