mysql - 插入多行时出现 NonUniqueObjectException 错误,LAST_INSERT_ID() 返回 0

标签 mysql asp.net-mvc nhibernate fluent-nhibernate

我在带有 MySQL 数据库的 ASP.NET MVC 应用程序中使用 NHibernate/Fluent NHibernate。我正在进行一项操作,该操作读取相当多的数据(相对于插入的数据量)、处理数据并最终插入(当前)大约 50 条记录。我每个请求有一个 ISession,它在开始/结束请求事件处理程序中创建/销毁(完全像 http://ayende.com/Blog/archive/2009/08/06/challenge-find-the-bug-fixes.aspx ),我正在读取数据并添加新对象(如第 16.3 节中的 https://www.hibernate.org/hib_docs/nhibernate/html/example-parentchild.html ),并且最后在 session 上调用 Flush() 以实际运行所有插入。

取出数据和延迟加载工作正常,当我调用 Flush 时恰好插入了 2 条新记录(我正在手动检查表以找出这一点),然后出现以下错误:

NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 0, of entity: ...

我是 NHibernate 的新手,在寻找解决方案时尝试将 Id 属性的生成器显式设置为 Native 和 Identity(它是一个 MySQL 数据库,Id 列是一个启用了 auto_increment 的 int),并显式设置未保存的Id 属性的值设置为 0。但是,我仍然收到错误。

我也试过在不同的时间调用 Flush(每次 INSERT 有效一次),然后我得到同样的错误,但是对于 0 以外的身份值和过程中看似随机的点(有时我没有得到它)都是在这种情况下,但有时我会在不同的时间点做)。

我不确定从这里去哪里。任何帮助或见解将不胜感激。

编辑:请参阅下面的答案。

最佳答案

编辑:我最初发布了一个不同的“答案”,但实际上并没有解决问题,但我想在这里为可能遇到它的任何其他人记录我的发现。

在尝试找出问题并解决这个问题几天后,我感到非常沮丧,因为这个问题似乎消失了一段时间,然后间歇性地回来了(让我多次认为我所做的改变修复了它,而实际上并没有),我相信我已经找到了真正的问题。

在我将 NHibernate 的 log4net 级别提高到 DEBUG 几次后,问题就消失了,但我终于能够在该日志级别上找到错误。日志中包含以下几行:

Building an IDbCommand object for the SqlString: SELECT LAST_INSERT_ID()
...
NHibernate.Type.Int32Type: 15:10:36 [8] DEBUG NHibernate.Type.Int32Type: returning '0' as column: LAST_INSERT_ID()
NHibernate.Id.IdentifierGeneratorFactory: 15:10:36 [8] DEBUG NHibernate.Id.IdentifierGeneratorFactory: 
Natively generated identity: 0

我只看了几行就看到了:

NHibernate.AdoNet.ConnectionManager: 15:10:36 [8] DEBUG NHibernate.AdoNet.ConnectionManager: aggressively releasing database connection
NHibernate.Connection.ConnectionProvider: 15:10:36 [8] DEBUG NHibernate.Connection.ConnectionProvider: Closing connection

似乎在刷新 session 和执行 INSERT 时,NHibernate 正在关闭 INSERT 语句和“SELECT LAST_INSERT_ID()”之间的连接以获取 MySQL 为 INSERT 语句生成的 ID。或者更确切地说,我应该说它是有时 关闭连接,这是我认为问题是间歇性的原因之一。我现在找不到链接,但我相信我也在所有搜索中读到,即使连接关闭并重新打开,MySQL 有时 也会从 LAST_INSERT_ID() 返回正确的值,这是另一个我认为这是间歇性的原因。但大多数情况下,如果连接关闭并在 INSERT 后重新打开,LAST_INSERT_ID() 将返回 0。

似乎有两种方法可以解决此问题。首先是补丁 available here看起来它将进入 NHibernate 2.1.1,或者您可以使用它来构建自己的 NHibernate,这会强制 INSERT 和 SELECT LAST_INSERT_ID() 一起运行。其次,您可以将 connection.release_mode 设置为 on_close,如 this blog post 中所述。这会阻止 NHibernate 在显式关闭 ISession 之前关闭连接。

我采用了后一种方法,它在 FluentNHibernate 中是这样完成的:

Fluently.Configure()
    ...
    .ExposeConfiguration(c => c.Properties.Add("connection.release_mode", "on_close"))
    ...

这也有大幅加速我的代码的副作用。之前需要 20-30 秒才能运行的程序(在我进行此更改之前它恰好可以运行)现在只需 7-10 秒,所以它在大约 1/3 的时间内完成了相同的工作。

关于mysql - 插入多行时出现 NonUniqueObjectException 错误,LAST_INSERT_ID() 返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1403390/

相关文章:

javascript - MVC项目经常JS修改后重新编译,不知道为什么,导致问题

mysql - 使用 MySQL 的 ASP.NET MVC Identity EF

c# - 关于 NHibernate 的 GuidCombGenerator 的几个问题

NHibernate 3 - 状态如何?

mysql group by 和 order by 不起作用

mysql - 根据查询结果从表中重新选择

asp.net-mvc - 具有延迟加载问题的工作单元方法、nHibernate、ASP.NET MVC、CaSTLe Windsor

c# - 如何更改 Fluent NHibernate 中小数的默认比例和精度?

php - Codeception-无法运行 dump.sql-(数据库中出现异常)SQLSTATE[42000] : Syntax error or access violation

Mysql表数据问题?