2010-02-05 22 views
9

Tengo una entidad llamada Libros que puede tener una lista de más libros llamada Libros relacionados.Fluido NHibernate Autorreferenciado a muchos a muchos

La entidad libro abreviado se ve algo le gusta a:

public class Book 
{ 
     public virtual long Id { get; private set; } 

     public virtual IList<Book> RelatedBooks { get; set; } 
} 

Esto es lo que la asignación se parece a esta relación

HasManyToMany(x => x.RelatedBooks) 
       .ParentKeyColumn("BookId") 
       .ChildKeyColumn("RelatedBookId") 
       .Table("RelatedBooks") 
       .Cascade.SaveUpdate(); 

Este es un ejemplo de los datos que se genera a continuación, en el Tabla de RelatedBooks:

BookId  RelatedBookId 
1   2 
1   3 

El problema ocurre cuando lo intento para borrar un libro. Si elimino el libro que tiene una ID de 1, todo funciona bien y la tabla RelatedBooks tiene eliminados los dos registros correspondientes. Sin embargo, si trato de eliminar el libro con un ID de 3, aparece el error "La instrucción DELETE entró en conflicto con la restricción de REFERENCIA" FK5B54405174BAB605 ". El conflicto ocurrió en la base de datos" Test ", tabla" dbo.RelatedBooks ", columna" RelatedBookId '".

Básicamente lo que está sucediendo es que el Libro no se puede eliminar porque el registro en la tabla de RelatedBooks que tiene un RelatedBookId de 3 nunca se elimina.

¿Cómo consigo que se elimine ese registro cuando elimino un libro?

EDITAR

Después de cambiar la cascada de SaveUpdate() para todo(), el mismo problema todavía existe si trato de borrar el libro con un ID de 3. También con Cascade programado en Todos() , si elimina el Libro con ID de 1, se borrarán los 3 libros (ID's: 1, 2 y 3), de modo que tampoco funcionarán.

Al observar el SQL que se ejecuta cuando se llama al método Book.Delete() cuando elimino el Libro con un ID de 3, parece que la instrucción SELECT está buscando en la columna incorrecta (lo que supongo que significa la sentencia SQL DELETE cometería el mismo error, por lo tanto, nunca eliminará ese registro). Aquí está el SQL para la RelatedBook

SELECT relatedboo0_.BookId as BookId3_ 
     , relatedboo0_.RelatedBookId as RelatedB2_3_ 
     , book1_.Id as Id14_0_ 

FROM RelatedBooks relatedboo0_ 
    left outer join [Book] book1_ on relatedboo0_.RelatedBookId=book1_.Id 

WHERE relatedboo0_.BookId=3 

La DONDE LA DECLARACIÓN debería ser algo como esto para el caso particular del thie:

WHERE relatedboo0_.RelatedBookId = 3 

SOLUCIÓN

aquí es lo que tenía que hacer para conseguir funciona para todos los casos

Asignación:

HasManyToMany(x => x.RelatedBooks) 
       .ParentKeyColumn("BookId") 
       .ChildKeyColumn("RelatedBookId") 
       .Table("RelatedBooks"); 

Código:

var book = currentSession.Get<Book>(bookId); 

if (book != null) 
{ 
    //Remove all of the Related Books 
    book.RelatedBooks.Clear(); 

    //Get all other books that have this book as a related book 
    var booksWithRelated = currentSession.CreateCriteria<Book>() 
           .CreateAlias("RelatedBooks", "br") 
           .Add(Restrictions.Eq("br.Id", book.Id)) 
           .List<Book>(); 

    //Remove this book as a Related Book for all other Books 
    foreach (var tempBook in booksWithRelated) 
    { 
     tempBook.RelatedBooks.Remove(book); 
     tempBook.Save(); 
    } 

    //Delete the book 
    book.Delete(); 
} 
+0

usted; re en el camino correcto, pero que la solución va a ser muy ineficiente porque se carga todos los libros y luego los filtra. Debería averiguar cómo volver a escribir para devolver solo los libros que tienen el libro que se eliminará en su colección de RelatedBooks. También podría considerar realizar esta operación a través de SQL. –

+0

Gracias, por el consejo. Se agregó una consulta de criterios de NHibernate para obtener solo esos libros. – Jeremy

Respuesta

4

En lugar de establecer el atributo de cascada, creo que es necesario simplemente vaciar la colección RelatedBooks antes de eliminar un libro.

book.RelatedBooks.Clear(); 
session.Delete(book); 

eliminaciones en cascada no se hace típicamente en una relación de muchos a muchos, ya que se elimina el objeto en el otro extremo de la relación, en este caso un libro.

Cuestiones relacionadas