2009-05-31 12 views
6

Ich habe folgendes Modell:löschen Würfen „gelöschte Objekt würde durch Kaskade neu gespeichert werden“

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

Es gibt keine Eigenschaften entweder in Person noch in Event PersonEventRegistration zeigt.

Wenn ich versuche, einen Eintrag aus PersonEventRegistration zu löschen, erhalte ich folgende Fehlermeldung:

"deleted object would be re-saved by cascade" 

Das Problem ist, ich weiß nicht speichern diese Aufgabe in jeder anderen Sammlung - der Lösch Code wie folgt aussieht:

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

Was mache ich hier falsch?

Antwort

3

Soweit ich weiß, cascade="all-delete-orphan" gehört auf die Sammlung Mapping-Element, nicht die many-to-one. Sie haben die anderen zwei Teile Ihres Mappings nicht gezeigt, so kann ich nicht sicher sagen, aber das ist (wahrscheinlich) das Problem möglich.

denke ich Person etwas aussehen sollte:

<!-- 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" ? --> /> 

Eigentlich könnte die oben widersprüchlichen Kaskaden sein (was sein könnte, was du hast). Also wirklich, meine Antwort ist zwei Dinge:

  1. cascade="all-delete-orphan" hat keine Bedeutung auf many-to-one.
  2. Stellen Sie sicher, dass Sie wirklich darüber nachgedacht haben, wie Sie mit Ihren Entitäten arbeiten und wie sie ihre Operationen kaskadieren sollten.
+0

ich diesen Beitrag nicht bemerkte nicht alle Formatierungen enthielt ... sowieso - das Ereignis und die Person-Zuordnungen enthalten keine Informationen über PersonEventRegistration. Diese Klasse wird verwendet, um das Viele-zu-Viele-Mapping und einige zusätzliche Attribute zu unterstützen (ich habe kein Beispiel gefunden, wo Nhibernate ein solches Szenario unterstützen würde). ich versuche cascade = "delete" trotzdem. – Greg

+2

Ihre Empfehlungen sind genau richtig. Es ist mehr als nur "' all-delete-orphan' hat keine Bedeutung ". Das Überschreiben eines Löschvorgangs von einem untergeordneten Element zu einem übergeordneten Element ist normalerweise _evil_. Das ist es, was "all" und "all-delete-orphan" auf einem "many-to-one" tun würde. Das Löschen der "PersonEventRegistration" mit diesen Kaskaden würde dazu führen, dass NHibernate versucht, die "Person" und das "Ereignis" ebenfalls zu löschen, was Greg nicht beabsichtigt. Aus diesem Grund schlägt das Löschen fehl, da die Person und das Ereignis weiterhin an anderer Stelle referenziert werden, sodass NHibernate sie nicht löschen kann. –

+0

... also ist die richtige Kaskade für ein "many-to-one" normalerweise 'save-update'. –

1

Try de-Referenzierung Person und Ereignis in der Lösch:

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

Auch ich war nicht bewusst, dass Sie eine Einschränkung auf ein Objekt hinzufügen könnte, würde ich dies mit Alias-Namen und IDs geschrieben .

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