【发布时间】:2011-12-24 19:28:19
【问题描述】:
我们正在尝试在抛出 StaleObjectStateException 后合并对象以保存合并副本。
这是我们的环境状况:
- 列表项
- 多用户系统
- WPF 桌面应用程序、SQL Server 2008 数据库
- NHibernate 3.1.0.4000,FluentNHibernate 1.2.0.712
- 全球、长期运行的 NHibernate 会话 [暂时。我们知道每个演示者会话是推荐的模式,但目前在我们的项目计划中没有时间进行转换。]
- 自上而下的保存和属性导航(也就是说我们在域图中保存了顶级对象(这里称为Parent))
- .Cascade.AllDeleteOrphan() 在大多数情况下使用。
- 用户独占域图中的某些对象,但共享父对象的所有权。
- 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):
您的会话及其加载的实体是 toast,因为使用 NHibernate,会引发异常 from a session 将该会话移至未定义状态。您不能再使用该会话 或任何加载的实体
C1 已经被现在不可用的会话分配了一个 ID 和版本号。 (我希望它没有。)
我们如何结合使用 ISession.Merge() 和 ISession.Refresh() 来获得一个新保存的同时具有 C1 和 C2 的 Parent ?
我们尝试了许多神秘的排列方式,但都没有完全奏效。 通常,“行已被另一个事务更新或删除(或未保存的值映射不正确”或 ODBC 级别的实际 ID 冲突。
我们目前的理论:
- 重置 C1 上的版本号(以防止“未保存的值映射不正确”)
- 获取新会话
- newSession.Refresh(C1);
- newParent = newSession.QueryOver[...]
- newParent.Add(C1);
- newSession.SaveOrUpdate(newParent)
但是,所有文档都表明 newSession.Merge 应该就足够了。
用作研究的其他帖子:
Fluent NHibernate Newbie: Row was updated or deleted by another transaction
Is there an alternative to ISession.Merge() that doesn't throw when using optimistic locking?
StaleObjectstateException row was updated or deleted by
How I can tell NHibernate to save only changed properties
Hibernate (JPA): how to handle StaleObjectStateException when several object has been modified and commited(java,但我认为是相关的)
【问题讨论】:
标签: nhibernate fluent-nhibernate optimistic-locking staleobjectstate