2 回答

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超4個(gè)贊
如果我理解正確,您正在嘗試更新Record與會(huì)話斷開(kāi)連接的對(duì)象。因此您可以使用Merge會(huì)話重新連接。
在這種情況下,為了使Merge您的集合工作,它們需要merge映射中的級(jí)聯(lián)選項(xiàng)。因此,請(qǐng)嘗試Fruits使用以下命令更新您的映射: cascade="merge,save-update"或簡(jiǎn)單地使用以下命令來(lái)更新您的映射cascade="all"以涵蓋所有情況:
<bag name="Fruits" table="tblRecordFruit" inverse="false" lazy="true" cascade="all">
PS調(diào)用實(shí)際上應(yīng)該與您現(xiàn)有的映射SaveOrUpdate一起正常工作。也許您在更新映射之前已經(jīng)嘗試過(guò),否則請(qǐng)確保異常相同并提供.Fruitscascade="save-update"Fruit
更新 1因此,如前所述,我假設(shè)您正在嘗試更新分離的實(shí)體(從不同會(huì)話加載的實(shí)體)。請(qǐng)確認(rèn)并提供詳細(xì)信息到底是如何發(fā)生的?它是否從 UI 上顯示的狀態(tài)進(jìn)行序列化/反序列化?
在這種情況下,您應(yīng)該意識(shí)到需要在保存對(duì)象后序列化狀態(tài)。因?yàn)楸4婧驠ruits集合類型更改為正確處理進(jìn)一步更新所需的內(nèi)部 NHibernate 集合。因此,當(dāng)record.Fruits.Add(obj)調(diào)用現(xiàn)有Record對(duì)象時(shí),它的類型record.Fruits一定不能List<T>是 NHibernate 類型(據(jù)說(shuō)PersistangGenericType<T>)。
因此,請(qǐng)確保您沒(méi)有覆蓋現(xiàn)有對(duì)象的集合屬性:
record.Fruits = new List<FruitType>();// WRONG for existing record...
//Instead clear existing record collection:
record.Fruits.Clear(); //Correct
還要在調(diào)試器中進(jìn)行以下檢查:
//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。這曾經(jīng)有效?,F(xiàn)在從 NHibernate v2 到 v4 的更改是否可能會(huì)導(dǎo)致此問(wèn)題?
我不知道它是如何在 NHibernate v2 中完成的 - 但它肯定可以在您的代碼中修復(fù)。所以你需要調(diào)查為什么它仍然存在List——這表明你做錯(cuò)了什么。一些建議:
1) 如果你的Fruits屬性有 setter - 刪除它以確保所有操作都是通過(guò)IList方法完成的:
public class Record
{
public virtual IList<FruitType> Fruits {get; } = new List<FruitType>()
}
2)調(diào)查這部分Then the user opens that record again and adds another FruitType to it.。你還沒(méi)說(shuō)它是如何實(shí)現(xiàn)的。這里的UI <-> Entity 映射是如何實(shí)現(xiàn)的?當(dāng)從數(shù)據(jù)庫(kù)加載現(xiàn)有實(shí)體時(shí),我很確定它不是ListNHibernate 類型。所以你應(yīng)該調(diào)試并找到它更改為 的地方List。
3) 還嘗試將級(jí)聯(lián)設(shè)置更改為cascade="all-delete-orphan"。我不認(rèn)為這會(huì)改變?nèi)魏问虑椤苑廊f(wàn)一。

TA貢獻(xiàn)1893條經(jīng)驗(yàn) 獲得超10個(gè)贊
例外情況:
違反主鍵約束“PK_tblRecordFruit_1”。無(wú)法在對(duì)象“dbo.tblRecordFruit”中插入重復(fù)的鍵。重復(fù)的鍵值為 (112, 53)。
說(shuō)違反了主鍵約束。這意味著您正在嘗試復(fù)制主鍵列的值。
查看映射中的以下代碼塊:
<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>
看來(lái)這RecordId是你在桌子上的主鍵tblRecordFruit。如果是這種情況,很明顯您無(wú)法將問(wèn)題中提到的示例數(shù)據(jù)插入到表中:
RecordId FruitTypeId
-----------------------
112 53
112 85
148 16
該值112不能在列中重復(fù)RecordId。如果您的代碼嘗試執(zhí)行此操作,很明顯您將得到您所說(shuō)的異常。
您是否正在尋找復(fù)合鍵(在 和RecordId列上FruitTypeId)?
首先,需要注意的是:復(fù)合鍵在 NHibernate 中當(dāng)然是可映射的,但它比典型的單個(gè)身份鍵要復(fù)雜一些。與普通密鑰相比,有一些額外的設(shè)置工作,查詢更加痛苦,并且它們?cè)谘舆t加載方面往往不太優(yōu)化。由于這些原因,經(jīng)驗(yàn)豐富的 NHibernate 用戶通常會(huì)盡可能避免使用復(fù)合鍵。
......
_
<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 關(guān)注
- 187 瀏覽
添加回答
舉報(bào)