У меня есть объект под названием Книги, которые могут иметь список большего количества книг под названием RelatedBooks.
Сокращенный Книжный объект смотрит, чему-то нравится это:
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
Проблема происходит когда я Попытка удалить книгу. Если я удаляю книгу, которая имеет идентификатор 1, все работает хорошо, и таблица RelatedBooks имеет две соответствующих удаленные записи. Однако, если я пытаюсь удалить книгу с идентификатором 3, я добираюсь, ошибка "Оператор удаления конфликтовала со ССЫЛОЧНЫМ ограничением "FK5B54405174BAB605". Конфликт произошел в базе данных "Test", таблица "dbo. RelatedBooks", столбец 'RelatedBookId'".
В основном то, что происходит, является Книгой, не может быть удален, потому что запись в таблице RelatedBooks, которая имеет RelatedBookId 3, никогда не удаляется.
Как я заставляю ту запись быть удаленной, когда я удаляю книгу?
Править
После изменения Каскада от SaveUpdate () ко Всем (), все еще существует та же проблема, если я пытаюсь удалить Книгу с идентификатором 3. Также с Каскадным набором ко Всем (), если удаляют Книгу с и идентификатор 1, то все 3 книги (идентификатор: 1, 2 и 3) удалены так, чтобы не работал также.
Рассмотрение SQL, который выполняется когда Книга. Удалите (), метод называют, когда я удаляю Книгу с идентификатором 3, похоже, что оператор SELECT смотрит на неправильный столбец (который я принимаю средства, что SQL УДАЛЯЕТ statment, сделал бы ту же ошибку, поэтому никогда не удаляя ту запись). Вот SQL для RelatedBook
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
ГДЕ statment должен выглядеть примерно так для thie особого случая:
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();
}
Rather than setting the cascade attribute, I think you need to simply empty the RelatedBooks collection before deleting a book.
book.RelatedBooks.Clear();
session.Delete(book);
Cascading deletes is not typically done in a many-to-many relationship because it will delete the object at the other end of the relationship, in this case a Book.
Это только что обновилось:
http://fluentnhibernate.lighthouseapp.com/projects/33236/tickets/115-self-referencing-relationships