当我更新实体时,如何处理NHibernate抛出“NonUniqueObjectReferenceException”
本文关键字:NHibernate 处理 抛出 NonUniqueObjectReferenceException 实体 更新 何处理 | 更新日期: 2023-09-27 18:23:37
我使用ISession.Query<T>().ToList()
获取对象列表,将它们添加到组合框中,以便用户可以浏览所有对象,然后编辑其中一个对象,并使用该对象调用ISession.Update()
。然而,这抛出了一个NonUniqueObjectReferenceException
。
为什么会发生这种情况,我应该使用什么方法来避免/解决这种情况?
问题说明
加载实体时,Session
会在Session
期间跟踪实体的数据库主键以及实体的对象reference
(内存中的位置)。
如果尝试将具有相同主键但对象reference
不同的实体持久化为该Session
的已加载实体,则会引发NonUniqueObjectReferenceException
。
换句话说,Session
告诉你,"我在内存中有一个实体,它的主键与你试图持久化的实体相同,但我的副本的对象reference
与你的副本不匹配。"
问题示例
- 打开
Session
(#1) - 加载实体(对象引用=A,数据库中的主键=1)
- 关闭
Session
- 打开一个新的
Session
(#2) - 再次加载同一实体(这一次,对象引用=B,数据库中的主键=1)
- 更改对象a的属性并将其持久化到
Session
#2中 - 将抛出
NonUniqueObjectReferenceException
值得注意的是,即使对象A只是会话2中持久化的较大对象图的一部分(即使对象A没有更改),也会抛出此异常。
还值得注意的是,您可以直接加载实体(Session.Load
、Session.Get
、Session.QueryOver
等)或间接加载实体(使用不返回对象但会将对象加载到内存中的查询)。NonUniqueObjectReferenceException
既可以用于直接加载的实体,也可以用于直接装载的实体。
重要提示:此问题可能由其他方面引起,例如,如果加载并克隆实体,然后使用此克隆使用Session
保留某些更改,则可能由单个Session
引起。原因是,克隆的对象reference
可能与原始实体不同。
解决方案说明
在Session
对象上有一个名为Merge
的方法:
object Session.Merge(object obj)
Merge
将获取一个实体,并使用该实体的主键从当前Session
中检索该实体的已加载版本。如果Session
的已加载实体的属性与您刚刚传递的实体不同,它还会更新这些实体的属性。
此方法不会更改传入的实体,而是返回一个您应该使用的不同对象。
关于Merge
的最后一个注意事项是,如果您所在的Session
内存中没有加载该实体的副本,那么Merge
将继续从数据库中加载该实体,然后再执行其通常的合并功能。
解决方案示例
// using the example above, we are at the beginning of step 6 inside session #2
// we have 2 important objects = ISession sessionTwo, Option objectA.
// Option is an entity defined by you, it is not part of NH.
objectA.SomeProperty = "blah";
var optionFromSessionTwo = (Option) sessionTwo.Merge(objectA);
// this will not throw and it will persist the changes to objectA
sessionTwo.Flush();
希望这能有所帮助!
Update()
。您应该使用事务或Flush()
来更新您的对象,如果您已经这样做了;从代码中删除session.Update()
就可以了。
这是NHibernate文档中适当的部分。
您需要阅读以下文档:
- 如何在Winforms上使用NHibernate
- "更新"的含义
快速解决方法是:不要调用session.Update()
,只调用session.Flush()
,这样更改就会反映到DB中。
session.Update()
不更新实体,会话透明地进行更新。Update和Save方法与INSERT和Update无关,相反,Save()
使瞬态对象持久化,而Update()
使分离的对象持久化。