2 回答

TA貢獻1946條經驗 獲得超4個贊
如果我理解正確,您正在嘗試更新Record與會話斷開連接的對象。因此您可以使用Merge會話重新連接。
在這種情況下,為了使Merge您的集合工作,它們需要merge映射中的級聯選項。因此,請嘗試Fruits使用以下命令更新您的映射: cascade="merge,save-update"或簡單地使用以下命令來更新您的映射cascade="all"以涵蓋所有情況:
<bag name="Fruits" table="tblRecordFruit" inverse="false" lazy="true" cascade="all">
PS調用實際上應該與您現有的映射SaveOrUpdate一起正常工作。也許您在更新映射之前已經嘗試過,否則請確保異常相同并提供.Fruitscascade="save-update"Fruit
更新 1因此,如前所述,我假設您正在嘗試更新分離的實體(從不同會話加載的實體)。請確認并提供詳細信息到底是如何發生的?它是否從 UI 上顯示的狀態進行序列化/反序列化?
在這種情況下,您應該意識到需要在保存對象后序列化狀態。因為保存后Fruits集合類型更改為正確處理進一步更新所需的內部 NHibernate 集合。因此,當record.Fruits.Add(obj)調用現有Record對象時,它的類型record.Fruits一定不能List<T>是 NHibernate 類型(據說PersistangGenericType<T>)。
因此,請確保您沒有覆蓋現有對象的集合屬性:
record.Fruits = new List<FruitType>();// WRONG for existing record...
//Instead clear existing record collection:
record.Fruits.Clear(); //Correct
還要在調試器中進行以下檢查:
//You somehow obtain record instance that you want to update
var record = DeserializeOrLoadState(recordId);
...//When you update existing record
record.Fruits.Add(fruitType1);// Make sure in debugger that for existing record record.Fruits is NHibernate type PesistentGenericBag<T> and not List<T>
...//When you SaveOrUpdate/Merge existing record
session.Merge(record);// <- make sure in debugger that for existing record.Fruits is NHibernate type PesistentGenericBag<T> and not List<T>
...
SerializeState(record);// serialize state only after session.SaveOrUpdate
更新2
它不是 PersistentGenericBag。這曾經有效。現在從 NHibernate v2 到 v4 的更改是否可能會導致此問題?
我不知道它是如何在 NHibernate v2 中完成的 - 但它肯定可以在您的代碼中修復。所以你需要調查為什么它仍然存在List——這表明你做錯了什么。一些建議:
1) 如果你的Fruits屬性有 setter - 刪除它以確保所有操作都是通過IList方法完成的:
public class Record
{
public virtual IList<FruitType> Fruits {get; } = new List<FruitType>()
}
2)調查這部分Then the user opens that record again and adds another FruitType to it.。你還沒說它是如何實現的。這里的UI <-> Entity 映射是如何實現的?當從數據庫加載現有實體時,我很確定它不是ListNHibernate 類型。所以你應該調試并找到它更改為 的地方List。
3) 還嘗試將級聯設置更改為cascade="all-delete-orphan"。我不認為這會改變任何事情——但以防萬一。

TA貢獻1893條經驗 獲得超10個贊
例外情況:
違反主鍵約束“PK_tblRecordFruit_1”。無法在對象“dbo.tblRecordFruit”中插入重復的鍵。重復的鍵值為 (112, 53)。
說違反了主鍵約束。這意味著您正在嘗試復制主鍵列的值。
查看映射中的以下代碼塊:
<bag name="Fruits" table="tblRecordFruit" inverse="false" lazy="true" cascade="save-update">
<key>
<column name="RecordId" length="4" sql-type="int" not-null="true" />
</key>
看來這RecordId是你在桌子上的主鍵tblRecordFruit。如果是這種情況,很明顯您無法將問題中提到的示例數據插入到表中:
RecordId FruitTypeId
-----------------------
112 53
112 85
148 16
該值112不能在列中重復RecordId。如果您的代碼嘗試執行此操作,很明顯您將得到您所說的異常。
您是否正在尋找復合鍵(在 和RecordId列上FruitTypeId)?
首先,需要注意的是:復合鍵在 NHibernate 中當然是可映射的,但它比典型的單個身份鍵要復雜一些。與普通密鑰相比,有一些額外的設置工作,查詢更加痛苦,并且它們在延遲加載方面往往不太優化。由于這些原因,經驗豐富的 NHibernate 用戶通常會盡可能避免使用復合鍵。
......
_
<composite-id>
<key-many-to-one class="SuperShop.Domain.OrderItemComponent,SuperShop.Domain" name="OrderItemComponent" column="OrderItemProductID" />
<key-property name="DetailType" column="DetailTypeID" type="SuperShop.Domain.DetailTypes,SuperShop.Domain" />
</composite-id>
<version name="LastModifiedOn"....
- 2 回答
- 0 關注
- 173 瀏覽
添加回答
舉報