NHibernate - 处理 StaleObjectStateException 以始终提交客户端更改 - 需要建议/推荐

2024-01-09

我正在尝试找到处理此异常的完美方法,并强制客户端更改覆盖导致冲突的任何其他更改。我想出的方法是将调用包装到Session.Transaction.Commit()在循环中,在循环内部,我将执行一个 try-catch 块,并通过复制其属性(行版本属性除外)单独处理每个陈旧对象,然后刷新对象以获取最新的数据库数据,然后将原始值重新复制到刷新的对象,然后进行合并。一旦我循环,我将提交,如果有其他的话StaleObjectStateException发生,则同样适用。循环不断循环,直到解决所有冲突。

此方法是 UnitOfWork 类的一部分。为了更清楚,我将发布我的代码:

// 'Client-wins' rules, any conflicts found will always cause client changes to
// overwrite anything else.
public void CommitAndRefresh() {
  bool saveFailed;

  do {
    try {
      _session.Transaction.Commit();
      _session.BeginTransaction();
      saveFailed = false;
    } catch (StaleObjectStateException ex) {
      saveFailed = true;

      // Get the staled object with client changes
      var staleObject = _session.Get(ex.EntityName, ex.Identifier);

      // Extract the row-version property name
      IClassMetadata meta = _sessionFactory.GetClassMetadata(ex.EntityName);
      string rowVersionPropertyName = meta.PropertyNames[meta.VersionProperty] as string;

      // Store all property values from client changes
      var propertyValues = new Dictionary<string, object>();
      var publicProperties = staleObject.GetType().GetProperties();
      foreach (var p in publicProperties) {
        if (p.Name != rowVersionPropertyName) {
          propertyValues.Add(p.Name, p.GetValue(staleObject, null));
        }
      }

      // Get latest data for staled object from the database
      _session.Refresh(staleObject);

      // Update the data with the original client changes except for row-version
      foreach (var p in publicProperties) {
        if (p.Name != rowVersionPropertyName) {
          p.SetValue(staleObject, propertyValues[p.Name], null);
        }
      }
      // Merge
      _session.Merge(staleObject);
    }
  } while (saveFailed);
}

上面的代码工作正常,并使用客户端获胜规则处理并发。但是,我想知道 NHibernate 中是否有任何内置功能可以为我执行此操作,或者是否有更好的方法来处理此问题。

提前致谢,


您所描述的是缺乏并发检查。如果不使用并发策略(乐观锁、版本锁或悲观锁),则不会抛出 StaleStateObjectException 并且会发出更新。


好的,现在我了解您的用例了。重要的一点是,抛出异常后应该丢弃 ISession。您可以使用 ISession.Merge 来合并分离的持久对象之间的更改,而不必自己执行此操作。不幸的是,合并不会级联到子对象,因此您仍然需要自己遍历对象图。所以实现看起来像这样:

catch (StaleObjectStateException ex)
{
    if (isPowerUser)
    {
        var newSession = GetSession();
        // Merge will automatically get first
        newSession.Merge(staleObject);
        newSession.Flush();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NHibernate - 处理 StaleObjectStateException 以始终提交客户端更改 - 需要建议/推荐 的相关文章

  • 无锁算法中的 ABA

    我明白了ABA http en wikipedia org wiki ABA problem问题 但我无法理解的是 他们说在语言中自动垃圾收集它可能不会展示 所以我的问题是 自动垃圾收集如何防止ABA问题的发生 在java中是否可能 如果可
  • 编写潜在并发问题的证明

    我正在阅读 Java 并发实践 并尝试编写一段代码来表明第 3 5 1 章中作为示例提供的类确实会引入问题 public class Holder public int n public Holder int n this n n publ
  • 与 data.table 合并时防止重复列

    我有两个数据表 它们的列名部分相似 dfA lt read table text A B C D E F G iso year matchcode 1 0 1 1 1 0 1 0 NLD 2010 NLD2010 2 1 0 0 0 1 0
  • Intel 64 和 IA-32 上的 MESI 有何意义

    MESI 的要点是保留共享内存系统的概念 然而 对于存储缓冲区 事情就变得复杂了 一旦数据到达 MESI 实现的缓存 下游内存就会保持一致 然而 在此之前 每个核心可能对内存位置 X 中的内容存在分歧 具体取决于每个核心的本地存储缓冲区中的
  • 如何在 cygwin 下配置 Mercurial 以使用 WinMerge 进行合并?

    当 Mercurial 在 cygwin 下运行时 弄清楚如何生成有点棘手WinMerge http winmerge org 来解决合并冲突 我怎样才能做到这一点 诀窍是 cygwin 路径与 Windows 路径不同 因此您需要一个小脚
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • 使用 SQLite 测试 NHibernate“没有这样的表” - 生成模式

    我正在尝试使用内存中的 SQLite 数据库来测试 NHibernate 提供的数据层 我读过很多关于如何进行此设置的博客和文章 但我现在很困惑为什么它不起作用 问题 当我运行单元测试时 我收到错误 没有这样的表 学生 我读过的文章表明这
  • Java Executor 根据 CPU 和 RAM 使用情况调整线程池

    我的应用程序使用 Executor 为大量任务提供线程池 通过分析和基准测试 我确定当每个核心有多个线程时 我的应用程序运行速度最快 一个好的启发式方法是从每个核心 4 个线程开始 不断变化 直到达到 gt 90 CPU 或 gt 90 R
  • 并发:C++11 内存模型中的原子性和易失性

    全局变量在 2 个不同内核上的 2 个并发运行的线程之间共享 线程对变量进行写入和读取 对于原子变量 一个线程可以读取过时的值吗 每个核心可能在其缓存中具有共享变量的值 并且当一个线程写入缓存中的其副本时 不同核心上的另一个线程可能会从其自
  • 合并具有一个共同元素的集合 R

    我有一个这样的列表 lista list lista 1 c 1 2 4 6 8 9 10 11 12 19 32 34 35 36 37 38 lista 2 c 7 8 lista 3 c 13 14 16 26 27 28 29 30
  • 如何组合 3 个或更多 CompletionStages?

    如果有 2 个 CompletionStages 我可以将它们与thenCombine method CompletionStage a aCompletionStage getA CompletionStage b bCompletion
  • git subtree pull -P 不管 总是合并冲突

    问题 即使我没有进行任何更改 每次尝试拉入子树时 我都会遇到合并冲突 我在做什么 In 子树仓库 Make some changes git commit am Changes made git push origin master In
  • 具有子集合成员条件的 NHibernate 查询仅返回部分子集合

    我与以下人员之间存在亲子关系Teacher and StudentReport Each StudentReport有一个时间戳字段记录老师完成报告的时间 我有一个查询 要查找截至某一分钟前已完成一份或多份报告的所有教师 public IL
  • 匿名结构和空结构

    http play golang org p vhaKi5uVmm http play golang org p vhaKi5uVmm package main import fmt var battle make chan string
  • NHibernate 具有多个数据库和事务

    我们在理解如何最好地使用 NHibernate 时遇到了一些问题 我们通常拥有相对大量 就表数量而言 的 SQL Server 数据库 而不是一个包含大量对象的数据库 我们正在研究处理多个会话工厂的各种选项 并且可能已经控制住了这一点 但是
  • 从实体获取单列

    如何从查询中获取单个列而不是整个对象 我可以这样做来获取整个对象 但我想要的只是名称 IList
  • Python 中的 Unix cat 函数 (cat * > merged.txt)? [复制]

    这个问题在这里已经有答案了 一旦建立了目录 有没有办法在Python中使用Unix中的cat函数或类似的函数 我想将 files 1 3 合并到 merged txt 我通常会在 Unix 中找到该目录 然后运行 cat gt merged
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • nHibernate 3 - Left Join re-Linq 解决方案

    我正在尝试使用 nHibernate 3 运行下面的 Linq 查询 var items from c in session Query
  • 在 Java EE 中手动启动新线程安全吗?

    对于在会话范围内的 JSF 托管 bean 中生成线程是否安全 我找不到明确的答案 线程需要调用无状态 EJB 实例 依赖注入到托管 bean 上的方法 背景是我们有一份需要很长时间才能生成的报告 由于我们无法更改服务器设置 这导致 HTT

随机推荐