我有一个名为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的Book,同样的问题仍然存在。同时将Cascade设置为All(),如果删除Book with和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();
}
答案 0 :(得分:4)
我认为您不需要设置级联属性,而是在删除书籍之前简单地清空RelatedBooks集合。
book.RelatedBooks.Clear();
session.Delete(book);
级联删除通常不是在多对多关系中完成的,因为它会删除关系另一端的对象,在本例中为Book。
答案 1 :(得分:0)