NHibernate的StaleObjectStateException之后如何优雅地合并对象图?

9
我们正在尝试在抛出StaleObjectStateException后合并对象以保存合并后的副本。
以下是我们的环境情况:
- 多用户系统 - WPF桌面应用程序,SQL Server 2008数据库 - NHibernate 3.1.0.4000,FluentNHibernate 1.2.0.712 - 全局长时间运行的NHibernate会话[目前为止。我们了解每个Presenter一个Session是推荐的模式,但目前项目进度没有时间进行转换。] - 自上而下的保存和属性导航(即我们在领域图中保存顶层对象(以下称为Parent)) - 在大多数情况下使用.Cascade.AllDeleteOrphan()。 - 用户独占领域图中的某些对象,但共享Parent的所有权。 - Children对象上不存在导航属性。 - 所有类都有数字ID和数字版本字段。
用例:
  • 用户1启动应用程序并打开父级。
  • 用户2启动应用程序并打开父级。
  • 用户2添加了一个子项(以下简称C2)。
  • 用户2保存了父级。
  • 用户1添加了一个子项(以下简称C1)。
  • 用户1保存了父级。
  • 用户1收到了StaleObjectStateException异常(理所当然)。

我们希望能够优雅地处理这个异常。 因为用户共享父级的所有权,所以用户1应该能够成功保存,并保存包括他的新子项和用户2的子项在内的父级。

当SOSE被抛出时,根据Ayende(http://msdn.microsoft.com/en-us/magazine/ee819139.aspx)的说法:

你的会话及其加载的实体都已经失效,因为在NHibernate中,从会话中抛出异常将会使该会话进入未定义状态。您不能再使用该会话或任何已加载的实体。

C1已经被无用的会话分配了ID和版本号。(但愿它没有被分配。)

我们如何结合使用ISession.Merge()和ISession.Refresh(),以获得同时具有C1和C2的新保存的父级?
我们尝试了许多复杂的排列组合,但没有一个完全起作用。通常会出现“行已被另一个事务更新或删除(或unsaved-value映射不正确)”或ODBC级别上实际ID冲突的情况。
我们目前的理论是:
  1. 重置C1的版本号(以防止“unsaved-value映射不正确”)
  2. 获取一个新会话
  3. newSession.Refresh(C1);
  4. newParent = newSession.QueryOver[...]
  5. newParent.Add(C1);
  6. newSession.SaveOrUpdate(newParent)
然而,所有文档都表明newSession.Merge应该足够。

其他用作研究的帖子:
Fluent NHibernate 新手:行已被另一个事务更新或删除
有没有一种替代 ISession.Merge() 的方法,在使用乐观锁定时不会抛出异常?
StaleObjectstateException 行已被更新或删除
如何告诉 NHibernate 仅保存已更改的属性
Hibernate(JPA):当多个对象已被修改和提交时如何处理 StaleObjectStateException(Java,但相关,我认为)

1个回答

2
由于用户共享父级的所有权,因此用户1应该能够成功保存,并将他的新子代和用户2的子代一起保存到父级中。
为什么不在子集上禁用乐观锁定呢?这样任何人都可以添加孩子,而不会增加父级的版本。
否则,这是我当前项目针对会话可能引发的所有可恢复异常(例如,与数据库的连接丢失,违反外键等)使用的解决方案:
1. 在调用session.Flush()之前,会话被序列化到MemoryStream中。 2. 如果session.Flush()或transaction.Commit()引发了可恢复的异常,则原始会话将被释放,已保存的会话将被反序列化。 3. 然后,调用屏幕会得到有关会话在异常后被恢复的信息,并再次调用在首次打开屏幕时调用的相同查询。由于所有修改过的实体仍然在恢复的会话中,因此用户现在具有刚按下保存按钮之前的状态。

看起来我们需要修复我们的映射文件,然后使用session.Replicate(obj, ReplicationMode.overwrite)——除非所有东西都是可序列化的,否则memorystream的东西不起作用,而且我们的版本号仍然会导致StaleObject。 - BufferUnderrunOK
注意:这仍然不是我最喜欢的答案,但cremor赢得了悬赏。 :) - BufferUnderrunOK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接