У меня есть объект под названием «Книги», в котором может быть список других книг под названием «Связанные книги».
Сокращенный объект 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();
Вот образец данных, которые затем создаются в таблице «Связанные книги»:
BookId RelatedBookId
1 2
1 3
Проблема возникает, когда я пытаюсь удалить книгу. Если я удалю книгу с идентификатором 1, все будет работать нормально, а из таблицы «Связанные книги» будут удалены две соответствующие записи. Однако, если я попытаюсь удалить книгу с идентификатором 3, я получаю сообщение об ошибке «Оператор DELETE конфликтует с ограничением REFERENCE« FK5B54405174BAB605 ». Конфликт произошел в базе данных« Test », таблица« dbo.RelatedBooks », столбец« RelatedBookId » '".
По сути, происходит то, что книга не может быть удалена, потому что запись в таблице RelatedBooks с идентификатором RelatedBookId, равным 3, никогда не удаляется.
Как мне удалить эту запись при удалении книги?
ИЗМЕНИТЬ
После изменения Cascade с SaveUpdate () на All () та же проблема все еще существует, если я попытаюсь удалить книгу с идентификатором 3. Также с Cascade, установленным на All (), при удалении книги с идентификатором 1, затем все 3 книги (ID: 1, 2 и 3) удаляются, так что это тоже не сработает.
Глядя на SQL, который выполняется, когда вызывается метод Book.Delete (), когда я удаляю книгу с идентификатором 3, похоже, что оператор SELECT смотрит не на тот столбец (что, как я предполагаю, означает, что статус SQL DELETE совершит ту же ошибку, поэтому никогда не удалит эту запись). Вот 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();
}