У меня такая же проблема ...
У меня есть объект, который имеет коллекцию, которая сопоставлена с таблицей, которая содержит уникальное ограничение.
Что я не понимаю, так это то, что согласно ответу Стюарта, удаление коллекции должно происходить до вставки коллекции?
Когда я погружаюсь в исходный код NHibernate, я нахожу класс CollectionUpdateAction
, который содержит этот код в методе Execute
:
persister.DeleteRows(collection, id, session);
persister.UpdateRows(collection, id, session);
persister.InsertRows(collection, id, session);
Тогда я бы предположил, что удаление выполняется перед вставкой, но, очевидно, это не так.
В этом сценарии не используется действие CollectionUpdateAction? Когда используется действие CollectionUpdateAction?
Ответ:
Я работал над этим следующим образом:
- В моем отображении я установил опцию каскада «удалить-сироту» вместо «все-удалить-сироту»
Весь мой доступ к базе данных осуществляется через репозиторий; в методе сохранения моего репозитория у меня есть этот код для моей сущности:
public void Save( Order orderObj )
{
// Only starts a transaction when there is no transaction
// associated yet with the session
With.Transaction(session, delegate()
{
session.SaveOrUpdate (orderObj);
session.Flush();
foreach( OrderLine line in orderObj.Lines )
{
session.SaveOrUpdate (line);
}
};
}
Итак, я сохраняю orderObj, и поскольку для каскада установлено значение Удалить-сирота, объекты, которые должны быть удалены, будут удалены из базы данных.
После того, как я позвоню SaveOrUpdate
, я должен обязательно сбросить изменения в базу данных.
Так как каскад удаления-удаления-сироты гарантирует, что никакие OrderLines не будут вставлены или обновлены, я должен перебрать мою коллекцию и вызвать 'SaveOrUpdate' для каждой OrderLine.
Это гарантирует, что будут добавлены новые OrderLines, а измененные обновлены.
Никакие действия не будут выполнены для OrderLines, которые не изменились.
Хотя это не идеальное решение (это безобразный взлом IMHO), оно вроде работает, и его абстрагируют от хранилища, так что сейчас я так решаю эту проблему ...