У меня есть два объекта в двунаправленном соотношении один-ко-многим:
public class Storage
{
public IList<Box> Boxes { get; set; }
}
public class Box
{
public Storage CurrentStorage { get; set; }
}
И отображение:
<class name="Storage">
<bag name="Boxes" cascade="all-delete-orphan" inverse="true">
<key column="Storage_Id" />
<one-to-many class="Box" />
</bag>
</class>
<class name="Box">
<many-to-one name="CurrentStorage" column="Storage_Id" />
</class>
A Storage
может иметь много Boxes
, но a Box
может принадлежать только одному Storage
.
Я их сопоставил так, что один-ко-многим имеет каскад all-delete-orphan
.
Моя проблема возникает, когда я пытаюсь изменить Box Storage
. Предполагая, что я уже запускал этот код:
var storage1 = new Storage();
var storage2 = new Storage();
storage1.Boxes.Add(new Box());
Session.Create(storage1);
Session.Create(storage2);
Следующий код даст мне исключение:
// get the first and only box in the DB
var existingBox = Database.GetBox().First();
// remove the box from storage1
existingBox.CurrentStorage.Boxes.Remove(existingBox);
// add the box to storage2 after it been removed from storage1
var storage2 = Database.GetStorage().Second();
storage2.Boxes.Add(existingBox);
Session.Flush(); // commit changes to DB
Я получаю следующее исключение:
NHibernate.ObjectDeletedException: удаленный объект будет повторно сохранен cascade (удалить удаленный объект из ассоциаций)
Это исключение возникает, потому что у меня есть каскадный набор all-delete-orphan
. Первый Storage
обнаружил, что я удалил Box
из своей коллекции и пометил ее для удаления. Однако, когда я добавил его ко второму Storage
(в том же сеансе), он попытается снова сохранить поле и ObjectDeletedException
.
Мой вопрос: как мне получить Box
, чтобы изменить родительский Storage
, не встречая этого исключения? Я знаю, что одним из возможных решений является изменение каскада только на all
, но затем я теряю способность NHibernate автоматически удалять Box
, просто удаляя его из Storage
и не переписывая его другим. Или это единственный способ сделать это, и мне нужно вручную вызвать Session.Delete
в поле, чтобы удалить его?