tablas relacionadas registros eliminar eliminacion ejemplos delete como cascada nhibernate nhibernate-mapping nhibernate-cascade

relacionadas - Obligando a NHibernate a eliminar en cascada antes de las inserciones



eliminar registros de tablas relacionadas sql server (3)

Estoy experimentando el mismo problema ... Tengo una entidad que tiene una colección que se asigna a una tabla que contiene una restricción única.

Lo que no entiendo es que, de acuerdo con la respuesta de Stuarts, ¿deberían ocurrir eliminaciones de la colección antes de las inserciones de la colección? Cuando me sumerjo en el código fuente de NHibernate, encuentro la clase CollectionUpdateAction , que contiene este código en su método Execute :

persister.DeleteRows(collection, id, session); persister.UpdateRows(collection, id, session); persister.InsertRows(collection, id, session);

Entonces, asumo que las eliminaciones se ejecutan antes que las inserciones, pero aparentemente este no es el caso. ¿No se utiliza CollectionUpdateAction en este escenario? ¿Cuándo se utiliza el CollectionUpdateAction?

Responder:

He trabajado alrededor de esto así:

  • En mi asignación, he establecido la opción de cascada en ''delete-orphan'' en lugar de ''all-delete-orphan''
  • Todo el acceso a mi base de datos se realiza a través de un repositorio; en el método de guardar de mi repositorio, tengo este código para mi entidad:

    public void Save( Order orderObj ) { // Only starts a transaction when there is no transaction // associated yet with the session With.Transaction(session, delegate() { session.SaveOrUpdate (orderObj); session.Flush(); foreach( OrderLine line in orderObj.Lines ) { session.SaveOrUpdate (line); } }; }

Por lo tanto, guardo el orderObj y la cascada está configurada para eliminar-huérfano, los objetos que se eliminarán, se eliminarán de la base de datos.

Después de llamar a SaveOrUpdate , debo asegurarme de vaciar los cambios en la base de datos.

Dado que la configuración de eliminar huérfano en cascada se asegura de que no se inserten o actualicen OrderLines, tengo que recorrer mi colección y llamar a ''SaveOrUpdate'' para cada OrderLine. Esto asegurará que se insertarán nuevas líneas de orden y se actualizarán las modificadas. No se realizará ninguna acción para OrderLines que no hayan cambiado.

A pesar de que no es la solución ideal (es un truco IMHO), funciona y se abstrae detrás del repositorio, así es como trato este problema por ahora ...

Tengo un objeto principal que tiene una relación de uno a varios con un ISet de objetos secundarios. Los objetos secundarios tienen una restricción única ( PageNum y PageNum : la clave externa para el padre).

<set name="Pages" inverse="true" cascade="all-delete-orphan" access="field.camelcase-underscore"> <key column="ContentId" /> <one-to-many class="DeveloperFusion.Domain.Entities.ContentPage, DeveloperFusion.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </set>

El problema que encontré es si quito un elemento ContentPage de la colección principal y luego agrego una nueva con la misma clave única dentro de la misma transacción ... Obtiene una violación de restricción única porque NHibernate intenta realizar la inserción antes la eliminación.

¿Hay alguna manera de forzar a NHibernate a realizar la eliminación primero?


No hay ninguna opción para especificar el orden de las operaciones en una transacción, ya que está codificado de la siguiente manera (de la documentación):

Las sentencias de SQL se emiten en el siguiente orden

  • todas las inserciones de entidad, en el mismo orden en que se guardaron los objetos correspondientes utilizando ISession.Save ()
  • todas las actualizaciones de la entidad
  • todas las eliminaciones de colección
  • Todas las eliminaciones de elementos de colección, actualizaciones e inserciones.
  • todas las inserciones de colección
  • todas las eliminaciones de entidades, en el mismo orden en que se eliminaron los objetos correspondientes utilizando ISession.Delete ()

(Una excepción es que los objetos que utilizan la generación de ID nativa se insertan cuando se guardan).

Como tal, ¿puedo desafiarlo a que responda por qué está agregando una nueva entidad con un identificador existente? Se supone que un identificador es exclusivo de una "entidad" específica. Si esa entidad se ha ido, también debería ser su identificador.

Otra opción sería hacer una actualización en ese registro en lugar de eliminar / insertar. Esto mantiene el ID igual, por lo que no hay una infracción de restricción única (al menos en la clave) y puede cambiar todos los demás datos para que sea un registro "nuevo".

EDIT: Así que aparentemente no estaba prestando atención por completo a la pregunta cuando respondí ya que este es un problema con una restricción única en una columna de clave no primaria.

Creo que tienes dos soluciones para elegir:

  1. Llame a Session.Flush() después de su eliminación, que ejecutará todos los cambios en la sesión hasta ese momento, después de lo cual podrá continuar con el resto (insertando su nuevo objeto). Esto también funciona dentro de una transacción, por lo que no necesita preocuparse por la atomicidad.
  2. Cree una función ReplacePage que actualice la entidad existente con datos nuevos, pero mantenga la clave principal y la columna única iguales.

Si se deshace de la clave principal secundaria (ContentPage.Id) y hace que la clave compuesta sea la clave principal (es decir, PageNum y ContentID), entonces creo que puede funcionar. Esta es una solución que se ofrece para el mismo problema que ocurre en la hibernación.