我有一個雙向一個一對多的關係的兩個實體:級聯爲delete-all-orphan時,如何在NHibernate中更改孩子的父級?
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>
一個Storage
可以有很多Boxes
,但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's been removed from storage1
var storage2 = Database.GetStorage().Second();
storage2.Boxes.Add(existingBox);
Session.Flush(); // commit changes to DB
我得到以下異常:
NHibernate.ObjectDeletedException:刪除的對象將是通過級聯重新保存(從關聯中刪除刪除的對象)
發生此異常是因爲級聯設置爲all-delete-orphan
。第一個Storage
檢測到我從集合中刪除Box
並將其標記爲刪除。但是,當我將其添加到第二個Storage
(在同一個會話中)時,它會嘗試再次保存該框並引發ObjectDeletedException
。
我的問題是,我如何獲得Box
更改其父母Storage
而不遇到此異常?我知道一個可能的解決方案是將級聯更改爲all
,但是然後我失去了讓NHibernate自動刪除Box
的能力,只需將其從Storage
中刪除即可,而不會將其重新與另一個關聯。或者這是唯一的方法來做到這一點,我必須手動撥打Session.Delete
在框中以刪除它?
如果您永遠不會從storage1中刪除該盒子,會發生什麼情況?如果只是將其移入存儲2,CurrentStorage是否會被覆蓋?我不確定在會話中storage1已經加載的情況下是否有效。 – dotjoe 2010-05-04 13:52:49
它的工作原理,但直到我刷新我的實體,我會在這兩個存儲中有一個框的副本。我寧願讓我的數據模型正確,而不是依靠NHib在檢索實體時做正確的事情。 – 2010-05-04 18:26:12
是的,如果你從收藏中刪除,孤兒總是會被刪除。我認爲在這種情況下,你最好像你說的那樣去做,你會想'cascade =「all」'並從集合中刪除並調用'session.Delete(box)'來刪除一個方框。我不認爲你可以擁有兩全其美的世界:( – dotjoe 2010-05-04 20:56:20