使用NHibernate插入失败后SQL不可用

时间:2012-10-18 19:37:53

标签: c# sql-server nhibernate

我有一个集成测试,它试图插入一个列,该列是另一行所具有的唯一列的副本。要插入行,我调用在我的实体存储库中找到的代码:

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_ 合同 _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,String resetOptionsString)      在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)      在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,DbAsyncResult result)      在System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult结果,String methodName,Boolean 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_ 合同 _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_ 合同 _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,String resetOptionsString)      在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)      在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,DbAsyncResult result)      在System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult结果,String methodName,Boolean 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_ 合同 _C51D43DA5070F446'。无法在对象' dbo.Contracts'中插入重复键。重复键值为(1005171)。   声明已经终止。

     

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

同步

从我所看到的,似乎insert语句将NHibernate置于失败状态。上面的更新代码抛出一个GenericADOException,表示SQL Not Available。我一定是在做错事。我应该以不同方式处理异常吗?

1 个答案:

答案 0 :(得分:2)

假设您使用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