fluent-nhibernate - 流利的NHibernate自引用多对多

标签 fluent-nhibernate many-to-many self-reference

我有一个名为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”冲突。冲突发生在数据库“测试”,表“dbo.RelatedBooks”,列“RelatedBookId” '”。

基本上,发生的事情是无法删除Book,因为从不删除RelatedBooks表中具有3的RelatedBookId的记录。

删除书籍时,如何删除该记录?

编辑

将Cascade从SaveUpdate()更改为All()后,如果我尝试删除ID为3的Book,则仍然存在相同的问题。如果Cascade设置为All(),如果删除ID为1的Book,则仍然存在相同的问题那么所有3本书(ID:1、2和3)都将被删除,因此也无法使用。

查看当我删除I​​D为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();
}

最佳答案

我认为您无需设置级联属性,而是只需在删除一本书之前先清空RelatedBooks集合。

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

级联删除通常不会在多对多关系中进行,因为它会删除关系另一端的对象(在本例中为Book)。

关于fluent-nhibernate - 流利的NHibernate自引用多对多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2211169/

相关文章:

.net - NHibernate - 如何映射到没有表的类(用于自定义 sql 查询)

java - Grails:GORM:遍历多对多关系

javascript - 替换新函数内的arguments.callee

javascript - 从自身内部调用方法?

forms - 使用自引用实体的 Symfony 表单渲染

c# - 流畅的 NHibernate 查询 : OrderBy column of joined table

c# - 将项目移动到另一个硬盘驱动器后的dll问题

fluent-nhibernate - 每个请求具有 Funq 和 FuentNHibernate session 的 ServiceStack

django - 获取objects.all()、reverse()或降序

python - SQLAlchemy 声明性语法中具有抽象基的多态多对多关系