9

我有一个名为 Books 的实体,它可以有一个名为 RelatedBooks 的更多书籍的列表。

缩写的 Book 实体看起来像这样:

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

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

这是这种关系的映射

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

以下是在 RelatedBooks 表中生成的数据示例:

BookId     RelatedBookId
1          2
1          3

当我尝试删除一本书时会出现问题。如果我删除 ID 为 1 的书,一切正常,RelatedBooks 表删除了两条相应的记录。但是,如果我尝试删除 ID 为 3 的图书,则会收到错误消息“DELETE 语句与 REFERENCE 约束“FK5B54405174BAB605”冲突。冲突发生在数据库“Test”、表“dbo.RelatedBooks”、列“RelatedBookId”中'”。

基本上正在发生的事情是无法删除 Book,因为 RelatedBooks 表中 RelatedBookId 为 3 的记录永远不会被删除。

当我删除一本书时,如何删除该记录?

编辑

将 Cascade 从 SaveUpdate() 更改为 All() 后,如果我尝试删除 ID 为 3 的书,同样的问题仍然存在。同样将 Cascade 设置为 All(),如果删除 ID 为 1 的书,然后所有 3 本书(ID:1、2 和 3)都被删除,这样也不起作用。

查看当我删除 ID 为 3 的 Book 时调用 Book.Delete() 方法时执行的 SQL,看起来 SELECT 语句正在查看错误的列(我假设这意味着 SQL DELETE 语句会犯同样的错误,因此永远不会删除该记录)。这是 RelatedBook 的 SQL

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 语句应该看起来像这样:

WHERE relatedboo0_.RelatedBookId = 3

解决方案

这是我必须做的才能让它适用于所有情况

映射:

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

代码:

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();
}
4

2 回答 2

4

而不是设置级联属性,我认为您需要在删除一本书之前简单地清空 RelatedBooks 集合。

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

级联删除通常不会在多对多关系中完成,因为它将删除关系另一端的对象,在本例中为 Book。

于 2010-02-08T15:26:18.317 回答
0

这刚刚更新:

http://fluentnhibernate.lighthouseapp.com/projects/33236/tickets/115-self-referencing-relationships

于 2010-05-04T16:55:58.287 回答