【问题标题】:SQL not available after a failed insert with NHibernate使用 NHibernate 插入失败后 SQL 不可用
【发布时间】:2012-10-18 19:37:53
【问题描述】:

我有一个集成测试,它尝试插入一行,其中的一列与另一行具有的唯一列重复。为了插入行,我调用了在我的实体存储库中找到的代码:

using (var transaction = rb.unitOfWork.Session.BeginTransaction())
        {
            try
            {
                ret = (Key)rb.unitOfWork.Session.Save(entity);
                transaction.Commit();
                rb.unitOfWork.Session.Clear();
            }
            catch
            {
                transaction.Rollback();
                rb.unitOfWork.Session.Clear();
                throw;
            }
        }

当这段代码与重复的实体一起运行时,我可以看到 NHibernate Profiler 上的插入。在该声明之后,我看到了以下警告和错误:

-- 声明 #1 警告: System.Data.SqlClient.SqlException (0x80131904):违反 UNIQUE KEY 约束“UQ_Contract_C51D43DA5070F446”。无法在对象“dbo.Contracts”中插入重复键。重复键值为 (1005171)。 该语句已终止。 在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj) 在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,字符串 resetOptionsString) 在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,布尔异步) 在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,String 方法,DbAsyncResult 结果) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult 结果,字符串方法名,布尔型 sendToPipe) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 在 System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand() 在 System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() 在 NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() 在 NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)

-- 声明 #2 错误: 违反 UNIQUE KEY 约束“UQ_Contract_C51D43DA5070F446”。无法在对象“dbo.Contracts”中插入重复键。重复键值为 (1005171)。 声明已终止。

-- 声明 #3 错误: 无法执行批处理命令。[SQL: SQL 不可用]无法将数据库状态与会话同步

-- 声明 #4 回滚事务

在这个测试之后,我做了很多查询测试,一切似乎都运行良好,直到我为同一个存储库点击更新语句。这是被调用的代码:

using (var transaction = rb.unitOfWork.Session.BeginTransaction())
        {
            rb.unitOfWork.Session.SaveOrUpdate(entity);
            transaction.Commit();
            rb.unitOfWork.Session.Clear();
        }
        rb.unitOfWork.Session.Evict(entity);

检查分析器显示更新被调用,紧接着,我得到这些语句:

-- 声明 #1 警告: System.Data.SqlClient.SqlException (0x80131904):违反 UNIQUE KEY 约束“UQ_Contract_C51D43DA5070F446”。无法在对象“dbo.Contracts”中插入重复键。重复键值为 (1005171)。 该语句已终止。 在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj) 在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,字符串 resetOptionsString) 在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,布尔异步) 在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,String 方法,DbAsyncResult 结果) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult 结果,字符串方法名,布尔型 sendToPipe) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 在 System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand() 在 System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() 在 NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() 在 NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)

-- 声明 #2 错误: 违反 UNIQUE KEY 约束“UQ_Contract_C51D43DA5070F446”。无法在对象“dbo.Contracts”中插入重复键。重复键值为 (1005171)。 声明已终止。

-- 声明 #3 错误: 无法执行批处理命令。[SQL: SQL 不可用]无法将数据库状态与会话同步

据我所见,插入语句似乎将 NHibernate 置于失败状态。上面的更新代码会引发一个 GenericADOException,它显示 SQL 不可用。我一定在这里做错了什么。我应该以不同的方式处理异常吗?

【问题讨论】:

    标签: c# sql-server nhibernate


    【解决方案1】:

    假设您使用 Identity 或任何其他 PostInsert Id 生成器,如果插入错误它仍然没有设置 id,并且下一个 SaveOrUpdate 将尝试再次插入它,因为它认为它是一个未保存的实例,从而再次导致错误。

    try {
        session.Save(entity);  // has duplicate key
    } catch {}
    
    Assert(entity.Id, Key.Unsaved);
    
    session.SaveOrUpdate(entity2); // will issue INSERT and throws again
    

    【讨论】:

      猜你喜欢
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 2016-10-28
      相关资源
      最近更新 更多