Удалить бросает "удаленный объект будет повторно сохранен каскадом" - PullRequest
6 голосов
/ 31 мая 2009

У меня есть следующая модель:

<class name="Person" table="Person" optimistic-lock="version">
  <id name="Id" type="Int32" unsaved-value="0">
    <generator class="native" />
  </id>
  <!-- plus some properties here -->
</class>

<class name="Event" table="Event" optimistic-lock="version">
  <id name="Id" type="Int32" unsaved-value="0">
    <generator class="native" />
  </id>
  <!-- plus some properties here -->
</class>

<class name="PersonEventRegistration" table="PersonEventRegistration" optimistic-lock="version">
  <id name="Id" type="Int32" unsaved-value="0">
    <generator class="native" />
  </id>
  <property name="IsComplete" type="Boolean" not-null="true" />
  <property name="RegistrationDate" type="DateTime" not-null="true" />
  <many-to-one name="Person" class="Person" column="PersonId" foreign-key="FK_PersonEvent_PersonId" cascade="all-delete-orphan" />
  <many-to-one name="Event" class="Event" column="EventId" foreign-key="FK_PersonEvent_EventId" cascade="all-delete-orphan" />
</class>

Нет свойств, указывающих на PersonEventRegistration ни в Person, ни в Event.

Когда я пытаюсь удалить запись из PersonEventRegistration, я получаю следующую ошибку:

"deleted object would be re-saved by cascade"

Проблема в том, что я не храню этот объект в любой другой коллекции - код удаления выглядит следующим образом:

public bool UnregisterFromEvent(Person person, Event entry)
{
    var registrationEntry = this.session
        .CreateCriteria<PersonEventRegistration>()
        .Add(Restrictions.Eq("Person", person))
        .Add(Restrictions.Eq("Event", entry))
        .Add(Restrictions.Eq("IsComplete", false))
        .UniqueResult<PersonEventRegistration>();

    bool result = false;
    if (null != registrationEntry)
    {
        using (ITransaction tx = this.session.BeginTransaction())
        {
            this.session.Delete(registrationEntry);
            tx.Commit();
            result = true;
        }
    }
    return result;
}

Что я здесь не так делаю?

Ответы [ 2 ]

3 голосов
/ 01 июня 2009

Насколько я знаю, cascade="all-delete-orphan" принадлежит элементу отображения коллекции, а не many-to-one. Вы не показали две другие части своего отображения, поэтому я не могу сказать наверняка, но это возможно (вероятно) проблема.

Я думаю Person должно выглядеть примерно так:

<!-- other properties -->
<set name="Events" inverse="true" cascade="all-delete-orphan">
    <key column="Person_id" />
    <one-to-many class="PersonEventRegistration" />
</set>

Event:

<!-- similar mapping for Event -->

PersonEventRegistration:

<!-- other properties -->
<many-to-one name="Person" class="Person" column="PersonId" foreign-key="FK_PersonEvent_PersonId" cascade="delete" <!-- or many ="all" ? --> />

На самом деле, вышеупомянутые могут быть конфликтующими каскадами (что может быть тем, что у вас есть). На самом деле, мой ответ - две вещи:

  1. cascade="all-delete-orphan" не имеет значения для many-to-one.
  2. Убедитесь, что вы действительно продумали, как вы работаете со своими сущностями и как они должны каскадно работать.
1 голос
/ 21 февраля 2010

Попробуйте удалить ссылку на Персона и Событие при удалении:

    public bool UnregisterFromEvent(Person person, Event entry)
    {
        var registrationEntry = this.session
            .CreateCriteria<PersonEventRegistration>()
            .Add(Restrictions.Eq("Person", person))
            .Add(Restrictions.Eq("Event", entry))
            .Add(Restrictions.Eq("IsComplete", false))
            .UniqueResult<PersonEventRegistration>();

        bool result = false;
        if (null != registrationEntry)
        {
            using (ITransaction tx = this.session.BeginTransaction())
            {
                registrationEntry.Person = null;
                registrationEntry.Event = null;
                this.session.Delete(registrationEntry);
                tx.Commit();
                result = true;
            }
        }
        return result;
    }

Кроме того, я не знал, что вы можете добавить ограничение на объект, я написал бы это, используя псевдонимы и идентификаторы.

            .Add(Restrictions.Eq("Person", person))
            .Add(Restrictions.Eq("Event", entry))
...