【问题标题】:NHibernate re-using identifiers when using session.SaveOrUpdateNHibernate 在使用 session.SaveOrUpdate 时重用标识符
【发布时间】:2017-01-27 18:41:43
【问题描述】:

我有一个客户已经运行我的程序几年了,他开始出现奇怪的错误。 我的应用程序在其中抛出异常:

Cannot insert duplicate key in object

由于我已经好几年没有接触过代码了,这让我很困惑。 而且只是偶尔发生。

经过大量调试并拔掉头发后,我弄清楚了发生了什么。

在将项目添加到数据库的代码中,我调用session.SaveOrUpdate

我不记得我选择这个而不是预期的session.Save 方法的具体原因,但让我们继续。 (不过,我正在为客户的代码更改它)。

所以似乎正在发生的事情是SaveOrUpdate 正在重新使用现有对象的 ID 并完全覆盖现有项目。我的代码抛出错误,但新项目已保存到数据库中,并且不再有原始记录的痕迹。在我的 nhibernate 映射文档中,我使用 hilo 生成器作为对象 ID。

我猜这只是因为数据库中现在有足够的项目来使 ID 重新启动或其他什么,我不知道。我确实有一个审计表,其中有/有很多记录。 10,000 的。但是我截断了该表以使备份更小。 (这可能会导致这个问题)。

我正在尝试找出是否有人可以最终说明 SaveOrUpdate 是否出于某种原因重复使用现有 ID,或者为什么现在将调用更改为 Save 有效。如果这是一个已知问题,我会轻松入睡,如果不是,我需要进一步调试以查看是否仍然存在客户端丢失数据的情况。

我的代码正在运行 Nhibernate 3.3.3.4000,这是我编写此应用程序时的最新代码。

更新 1

Session.Save 也在重复使用 ID。

在插入新记录时,我不断收到重复键错误。但不是每次,只有几次。所以它非常随机,很难调试。

【问题讨论】:

    标签: c# session nhibernate fluent-nhibernate


    【解决方案1】:

    NHibernate 用户请求了一种通用方法,该方法要么通过生成新标识符来保存瞬态实例,要么更新与其当前标识符关联的持久状态。 SaveOrUpdate() 方法现在实现了这个功能。

    http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-updating-detached)

    基于此,您假设SaveOrUpdate() 的行为将成立,如果 NH 在测试它是“瞬态”还是“持久”之前分配了对象的键。 IE。密钥生成器分配一个恰好被使用的密钥,然后保存或更新逻辑倾向于更新,因为它确定对象是“持久的”。如果这是实际发生的事情,我会感到惊讶,因为这似乎是一个非常基本的错误。

    如果您启用日志记录,您将能够确定是否确实如此。

    【讨论】:

    • 被覆盖的记录是在几个月/几年前创建的,而不是在当前会话或事务中。在调用 flush 之前,在 session.save 之后,新记录的 ID 已经分配了一个先前存在的项目的 ID。 Session.save 也是这样做的。
    • ...我猜这就是产生重复键错误的原因?我可以理解这种行为。我不明白现有数据是如何被覆盖的。
    • 你和我。如果我在执行代码时逐行跳过代码,我可以看到对 session.save 的调用为我的新记录分配了一个 ID。如果我去 sql management studio 并使用该 ID 查询数据,它是一个完全不同的记录。然后,事务提交后,原始记录完全没有了,即使我根据其他值搜索它。我可能还应该提到的一件事是有一个 ADO 异常,它表明存在主键违规,但我正在捕获该异常并提交(是的,我知道不好)。我修复它以回滚
    【解决方案2】:

    我花了很多时间试图解决这个问题,但最终我还是放弃了。

    到目前为止,我的解决方案似乎可行,是将 nhibernate id 生成器类从 hilo 更改为 native

    这确实需要我导出并重新导入我的所有数据,以便我可以重建表格,因此对于找到此帖子的其他人来说可能不是一个很好的解决方案,除非他们手动更改表格上的身份。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      相关资源
      最近更新 更多