2009-05-31 6 views
6

he siguiente modelo:Eliminar tiros "objeto eliminado sería re-salvados por la cascada"

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

No hay propiedades que apunta a PersonEventRegistration ya sea en persona, ni en el Evento.

Cuando intento eliminar una entrada de PersonEventRegistration, me sale el siguiente error:

"deleted object would be re-saved by cascade" 

El problema es que no se debe de conservar este objeto en cualquier otra colección - el código de eliminación se ve así:

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

¿Qué estoy haciendo mal aquí?

Respuesta

3

Por lo que sé, cascade="all-delete-orphan" pertenece al elemento de asignación de la colección, no al many-to-one. No has mostrado las otras dos partes de tu mapeo, así que no puedo decirlo con certeza, pero es posible (probablemente) el problema.

creo Person debería ser algo como:

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

En realidad, lo anterior podría ser cascadas en conflicto (que podría ser lo tienes). Así que en realidad, mi respuesta es dos cosas:

  1. cascade="all-delete-orphan" no tiene ningún significado en many-to-one.
  2. Asegúrate de haber pensado realmente cómo estás trabajando con tus entidades y cómo deben poner en cascada sus operaciones.
+0

No me di cuenta de que después no contenía todo el formato ... de todos modos - la persona asignaciones de los eventos y no contienen ninguna información sobre PersonEventRegistration. esta clase se usa para admitir el mapeo muchos-a-muchos + algunos atributos adicionales (no encontré ningún ejemplo donde nhibernate soportaría tal escenario). intentaré cascade = "eliminar" de todos modos. – Greg

+2

Sus recomendaciones son acertadas. Es más que simplemente "' all-delete-huérfano' no tiene significado ". Conectar en cascada una eliminación de un hijo hasta un padre suele ser _evil_. Eso es lo que harían 'all' y' all-delete-huérfano' en un '' muchos a uno''. Al eliminar el 'PersonEventRegistration' con esas cascadas, NHibernate intentará eliminar también' Person' y 'Event', lo que seguramente no es lo que pretende Greg. Y es por eso que la eliminación falla, porque la Persona y el Evento todavía se mencionan en otra parte, por lo que NHibernate no puede eliminarlos. –

+0

... por lo que la cascada correcta para un 'muchos-a-uno' suele ser' save-update'. –

1

Trate de referencias persona y evento en el borrado:

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

Además, yo no era consciente de que se podría añadir una restricción sobre un objeto, habría escrito este uso de alias y los ID .

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