2008-11-19 15 views
74

Tengo un objeto principal que tiene una relación uno a muchos con un IList de objetos secundarios. ¿Cuál es la mejor manera de eliminar los objetos secundarios? No estoy eliminando el padre. Mi objeto primario contiene un IList de objetos secundarios. Esta es la asignación para el uno a muchos:Cómo eliminar un objeto secundario en NHibernate?

<bag name="Tiers" cascade="all"> 
    <key column="mismatch_id_no" /> 
    <one-to-many class="TGR_BL.PromoTier,TGR_BL"/> 
</bag> 

Si intento para eliminar todos los objetos de la colección usando clara(), y luego llamar saveOrUpdate(), me sale esta excepción:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 

Si trato de eliminar los objetos secundarios de forma individual y luego eliminarlos de la matriz, me sale una excepción:

deleted object would be re-saved by cascade 

Esta es mi primera vez tratando con la eliminación de los objetos secundarios en NHibernate. ¿Qué estoy haciendo mal?

editar: Solo para aclarar: NO trato de eliminar el objeto principal, solo los objetos secundarios. Tengo la relación establecida como uno a muchos en el padre. ¿También necesito crear una relación de muchos a uno en el mapeo de objetos hijo?

Respuesta

130

Recibirá el primer error porque, cuando elimina los elementos de la colección, el modo de funcionamiento predeterminado de NHibernate es simplemente romper la asociación. En la base de datos, NHibernate intenta establecer que la columna de la clave externa en la fila secundaria sea nula. Como no permite valores nulos en esa columna, SQL Server genera el error. La eliminación de la colección no necesariamente eliminará el objeto hijo, pero una forma de hacerlo es establecer cascade = all-delete-huérfano. Esto informa a NHibernate que debe eliminar las filas recientemente huérfanas en lugar de establecer la columna de clave externa.

Aparecerá el segundo error porque al llamar a SaveOrUpdate, NHibernate elimina por primera vez todos los objetos secundarios. Entonces, dado que ninguna de las relaciones está marcada como inversa, NHibernate también intenta establecer la columna de clave externa en su tabla secundaria como nula. Como las filas ya se han eliminado, recibirá el segundo error. Debes establecer inverse = true en un lado de tu relación para arreglar esto. Esto generalmente se hace en el lado de una (clave principal o padre). Si no hace esto, NHibernate hará las actualizaciones apropiadas para cada lado de la relación. Desafortunadamente, ejecutar dos actualizaciones no es lo apropiado.

Siempre debe marcar un lado de sus relaciones como el lado inverso. Dependiendo de cómo codifique, puede o no necesitar usar cascada. Si desea aprovechar la eliminación de una toma ya que está tratando de hacerlo con Clear(), necesita definir su cascada.

+0

Solo para aclarar: solo tengo la relación definida en el objeto Parent en este momento. Intenté establecer la cascada de ese objeto en "todos" y "eliminar todo-huérfano" con los mismos resultados en ambas ocasiones. ¿Quiere decir que también necesito definir una relación de muchos a uno en el objeto hijo? –

+0

Y en este caso does inverse = "true" pertenece al objeto primario o secundario? –

+2

pertenece a la clase que no tiene la clave externa ... generalmente el padre. – pmlarocque

-3

conjunto Not-Null = verdadero en su asignación en la columna que causa el problema. Aunque no estoy seguro de la sintaxis exacta (lo siento).

+0

Ok, configuré la columna como no-null = "true" en el mapeo del objeto hijo. Entonces, llamo al método clear() en el IList de objetos secundarios, luego pruebo SaveOrUpdate(). Todavía aparece el error "No se puede insertar el valor NULL en la columna". ¿Estoy haciendo algo más mal? –

+0

¿en qué columna se está produciendo el error? ¿cómo estás eliminando a los niños en tu modelo? –

+0

Llamo al método clear() en el objeto hijo Ilist en mi objeto primario. Luego estoy llamando a SaveOrUpdate() en el padre. –

0

Cambie el valor del atributo de cascada de "all" a "all-delete-huérfano".

+0

Probé esto. Todavía recibo la misma excepción. –

+16

all-delete-huérfano borra los elementos secundarios cuando elimina el elemento primario. no tiene nada que ver con eliminar a los niños como este tipo está preguntando. –

2

Intente utilizar merge() en lugar de saveOrUpdate(). Además, asegúrese de que su cascada esté configurada como "eliminar todo-huérfano" y que su relación padre-hijo sea invertible (inverso = verdadero en el padre y luego un campo en el hijo que sea el padre-id con no-nulo = verdadero) .

2

En nuestro ejemplo, tenemos categorías con muchos productos en los que un producto no puede contener nulos.

Puede solucionar el problema eliminando el producto y quitándolo de la colección principal antes del color, pero aún estamos buscando una solución mejor para esto.

product = pRepo.GetByID(newProduct.ProductID); 
product.Category.Products.Remove(product); 
pRepo.Delete(product); 

creo que sirve de todos modos

+0

Esto requiere otro repositorio. – UpTheCreek

3

según la respuesta de Chuck, he resuelto mi problema mediante la adición inversa = true en la cartografía lado de los padres:

mensaje tiene muchas MessageSentTo:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)] 
public IList<MessageSentTo> MessageSendTos 
{ 
    get { return m_MessageSendTo; } 
    set { m_MessageSendTo = value; } 
} 

Estoy usando Castle ActiveRecord. Gracias Chuck.

Cuestiones relacionadas