私は、RelatedBooks という書籍のリストを持つことができる Books というエンティティを持っています。
省略された 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 テーブルから対応する 2 つのレコードが削除されます。ただし、ID が 3 の本を削除しようとすると、「DELETE ステートメントが REFERENCE 制約 "FK5B54405174BAB605" と競合しています。データベース "Test"、テーブル "dbo.RelatedBooks"、列 'RelatedBookId で競合が発生しました」というエラーが表示されます。 」。
基本的に、RelatedBookId が 3 の RelatedBooks テーブルのレコードは削除されないため、Book を削除できません。
本を削除するときにそのレコードを削除するにはどうすればよいですか?
編集
Cascade を SaveUpdate() から All() に変更した後、ID が 3 の Book を削除しようとすると、同じ問題が引き続き発生します。また、Cascade を All() に設定し、ID が 1 の Book を削除すると、次に、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();
}