2010-02-05 4 views
9

J'ai une entité appelée Livres qui peuvent avoir une liste de plus de livres appelés RelatedBooks.NHibernate Fluent auto référençant beaucoup à beaucoup

L'entité du livre abrégé ressemble à quelque chose aime ça:

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

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

Voici ce que le mapping ressemble à cette relation

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

Voici un échantillon des données qui est alors généré dans le Tableau desConnexes similaires:

BookId  RelatedBookId 
1   2 
1   3 

Le problème se produit lorsque j'essaie pour supprimer un livre. Si je supprime le livre qui a un ID de 1, tout fonctionne bien et la table RelatedBooks a les deux enregistrements correspondants supprimés. Cependant, si j'essaie de supprimer le livre avec un ID de 3, j'obtiens l'erreur "L'instruction DELETE est en conflit avec la contrainte REFERENCE" FK5B54405174BAB605 ".Le conflit est survenu dans la base de données" Test ", table" dbo.RelatedBooks ", colonne 'RelatedBookId "".

Fondamentalement ce qui se passe est le livre ne peut pas être supprimé parce que l'enregistrement dans la table RelatedBooks qui a un RelatedBookId de 3 n'est jamais supprimé.

Comment puis-je supprimer cet enregistrement lorsque je supprime un livre?

EDIT

Après avoir modifié la Cascade de SaveUpdate() à tous(), le même problème existe toujours si je tente de supprimer le livre avec un ID de 3. Aussi avec Cascade réglé sur All() , si vous supprimez le livre avec et ID de 1, alors tous les 3 livres (ID: 1, 2 et 3) sont supprimés, ce qui ne fonctionnera pas non plus. En regardant le SQL qui est exécuté lorsque la méthode Book.Delete() est appelée lorsque je supprime le livre avec un ID de 3, il semble que l'instruction SELECT regarde la mauvaise colonne (ce qui, je suppose, signifie que la déclaration SQL DELETE ferait la même erreur, donc ne supprimant jamais cet enregistrement). Voici le SQL pour le 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 

WHERE statment devrait ressembler à ceci pour le cas particulier Thie:

WHERE relatedboo0_.RelatedBookId = 3 

SOLUTION

est ce que je ici devais faire pour il fonctionne pour tous les cas

Cartographie:

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

code:

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

Vous, re sur la bonne voie, mais cette solution va être très inefficace, car il charge tous les livres puis les filtres. Vous devriez comprendre comment le réécrire pour retourner seulement les livres qui ont le livre à supprimer dans leur collection RelatedBooks. Vous pouvez également envisager d'effectuer cette opération via SQL. –

+0

Merci, pour le conseil. Ajout d'une requête de critères NHibernate pour obtenir uniquement ces livres. – Jeremy

Répondre

4

Plutôt que de définir l'attribut cascade, je pense que vous devez vider simplement la collection RelatedBooks avant de supprimer un livre.

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

n'est pas Cascading supprime généralement fait dans un grand nombre à plusieurs rapports, car elle supprime l'objet à l'autre bout de la relation, dans ce cas, un livre.

Questions connexes