Устойчивость ребенка к отношениям один-к-одному не удается после обновления до NHibernate 3 - PullRequest
1 голос
/ 12 мая 2011

Я обновляю старое решение NHibernate 1.2, которое я перенес на NHib 3.1.У нас проблемы с сохранением отношений родитель-потомок.Что дает нам эту ошибку:

NHibernate.StaleObjectStateException: строка была обновлена ​​или удалена другой транзакцией (или отображение несохраненного значения было неправильным)

Этот код работал в NHib 1.2, но не работаетв 3.1

Мы сохраняем так же, как этот код ниже:

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.

Однако, если мы сохраним r, то f и сбросит это работает.

Я бы хотелзнать, почему это происходит, почему изменения между версиями NHib.Это то, как сессион думает, что сущности сейчас преходящи?Он обрабатывает генератор идентификатора внешнего ключа по-другому?

На примечании сторон, идентификатор рецепта не равен идентификатору фильма, который я ожидал бы сделать.

HMB файлы.- ОБНОВЛЕНО, чтобы включить полные файлы

Фильм:

<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>

Рецепт:

<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>

Ответы [ 2 ]

0 голосов
/ 12 мая 2011

Из документации: http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-onetoone

Связи первичных ключей не нуждаются в дополнительном столбце таблицы;если две строки связаны ассоциацией, то две строки таблицы имеют одинаковое значение первичного ключа.Поэтому, если вы хотите, чтобы два объекта были связаны ассоциацией первичного ключа, вы должны убедиться, что им присвоено одно и то же значение идентификатора!

Для ассоциации первичного ключа добавьте следующие сопоставления в Employee и Person соответственно.

<one-to-one name="Person" class="Person"/>

<one-to-one name="Employee" class="Employee" constrained="true"/>

Теперь мы должны убедиться, что первичные ключи связанных строк в таблицах PERSON и EMPLOYEE равны.Мы используем специальную стратегию создания идентификатора NHibernate, которая называется foreign:

<class name="Person" table="PERSON">
    <id name="Id" column="PERSON_ID">
        <generator class="foreign">
            <param name="property">Employee</param>
        </generator>
    </id>
    ...
    <one-to-one name="Employee"
        class="Employee"
        constrained="true"/>
</class>

Вновь сохраненному экземпляру Person присваивается то же значение первичного ключа, что и для экземпляра Employee, на который ссылается свойство Employeeэтот человек.

0 голосов
/ 12 мая 2011

Если у вас есть каскадное сохранение «дочернего» объекта, вы просто сохраняете родительский объект.Вам не нужно спасать ребенка.

Так что здесь вы должны попробовать сохранить только "f".

...