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 关注
- 129 浏览
添加回答
举报