Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在NHibernate StaleObjectStateException之后优雅地合并对象图?_Nhibernate_Fluent Nhibernate_Optimistic Locking_Staleobjectstate - Fatal编程技术网

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

如何在NHibernate StaleObjectStateException之后优雅地合并对象图?,nhibernate,fluent-nhibernate,optimistic-locking,staleobjectstate,Nhibernate,Fluent Nhibernate,Optimistic Locking,Staleobjectstate,我们正在尝试在抛出StaleObjectStateException以保存合并副本后合并对象 以下是我们的环境状况: 列表项 多用户系统 WPF桌面应用程序,SQL Server 2008数据库 NHibernate 3.1.0.4000,FluentNHibernate 1.2.0.712 全局、长期运行的NHibernate会话[目前,我们了解每个演示者的会话是推荐的模式,但目前在我们的项目计划中没有时间转换。] 自顶向下保存和属性导航(也就是说,我们在域图中保存顶级对象(这里称为父对象)

我们正在尝试在抛出StaleObjectStateException以保存合并副本后合并对象

以下是我们的环境状况:

  • 列表项
  • 多用户系统
  • WPF桌面应用程序,SQL Server 2008数据库
  • NHibernate 3.1.0.4000,FluentNHibernate 1.2.0.712
  • 全局、长期运行的NHibernate会话[目前,我们了解每个演示者的会话是推荐的模式,但目前在我们的项目计划中没有时间转换。]
  • 自顶向下保存和属性导航(也就是说,我们在域图中保存顶级对象(这里称为父对象)
  • .Cascade.AllDeleteOrphan()在大多数情况下使用
  • 用户独占域图中的某些对象,但共享父对象的所有权
  • 子对象上的导航属性不存在
  • 所有类都有数字ID和数字版本字段
用例:

  • 用户1启动应用程序并打开父级
  • 用户2启动应用程序并打开父级
  • 用户2添加子级(此处为C2)
  • 用户2保存父项
  • 用户1添加子级(这里是C1)
  • 用户1保存父项
  • 用户1收到一个StaleObjectStateException(正确地说是这样的)
我们想优雅地处理这个异常。 因为用户共享父级的所有权,所以用户1应该能够成功保存,并将父级与其新的子级和用户2的子级一起保存

当抛出SOSE时,根据Ayende():

您的会话及其加载的实体是toast,因为对于NHibernate,会引发异常 从会话将该会话移动到未定义状态。您不能再使用该会话 或任何加载的实体

C1已经被现在不有用的会话分配了一个ID和版本。(但愿不是这样。)

我们如何结合使用ISession.Merge()和ISession.Refresh()来获得新保存的同时具有C1和C2的父级

我们已经尝试了许多神秘的排列,但没有一种完全有效。 通常,“行被另一个事务更新或删除(或未保存的值映射不正确)”或ODBC级别的实际ID冲突

我们目前的理论是:

  • 重置C1上的版本号(以防止“未保存的值映射不正确”)
  • 获取新会话
  • 新闻会话刷新(C1)
  • newParent=newSession.QueryOver[…]
  • newParent.Add(C1)
  • newSession.SaveOrUpdate(newParent)
  • 然而,所有的文档都表明newSession.Merge应该足够了

    用作研究的其他职位:




    (java,但我认为是相关的)

    因为用户共享父级的所有权,所以用户1应该能够成功保存,并将父级与其新的子级和用户2的子级一起保存

    为什么不禁用子集合上的乐观锁定?这样任何人都可以添加子集合,而不会增加父集合的版本

    否则,以下是我当前项目用于会话可能引发的所有可恢复异常的解决方案(例如,与DB的连接丢失、外键冲突等):

  • 调用
    session.Flush()
    之前,会话被序列化为
    MemoryStream
  • 如果
    session.Flush()
    transaction.Commit()
    引发可恢复的异常,则原始会话将被释放,保存的会话将被反序列化
  • 然后,调用屏幕获取异常后会话恢复的信息,并再次调用第一次打开屏幕时调用的相同查询。由于所有修改的实体仍在恢复的会话中,用户现在的状态是在按下save之前

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