c# - 使用 NHibernate 插入失败后 SQL 不可用

标签 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 上看到插入。在该声明之后,我看到了这些警告和错误:

-- statement #1 WARN: System.Data.SqlClient.SqlException (0x80131904): Violation of UNIQUE KEY constraint 'UQ_Contract_C51D43DA5070F446'. Cannot insert duplicate key in object 'dbo.Contracts'. The duplicate key value is (1005171). The statement has been terminated. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand() at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)

-- statement #2 ERROR: Violation of UNIQUE KEY constraint 'UQ_Contract_C51D43DA5070F446'. Cannot insert duplicate key in object 'dbo.Contracts'. The duplicate key value is (1005171). The statement has been terminated.

-- statement #3 ERROR: could not execute batch command.[SQL: SQL not available]Could not synchronize database state with session

-- statement #4 rollback transaction

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

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

检查探查器显示更新被调用,但在那之后,我得到了这些语句:

-- statement #1 WARN: System.Data.SqlClient.SqlException (0x80131904): Violation of UNIQUE KEY constraint 'UQ_Contract_C51D43DA5070F446'. Cannot insert duplicate key in object 'dbo.Contracts'. The duplicate key value is (1005171). The statement has been terminated. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.SqlClient.SqlCommand.ExecuteBatchRPCCommand() at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)

-- statement #2 ERROR: Violation of UNIQUE KEY constraint 'UQ_Contract_C51D43DA5070F446'. Cannot insert duplicate key in object 'dbo.Contracts'. The duplicate key value is (1005171). The statement has been terminated.

-- statement #3 ERROR: could not execute batch command.[SQL: SQL not available]Could not synchronize database state with session

据我所知,插入语句似乎使 NHibernate 进入失败状态。上面的更新代码抛出一个 GenericADOException,指出 SQL 不可用。我一定是在这里做错了什么。我应该以不同的方式处理异常吗?

最佳答案

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

关于c# - 使用 NHibernate 插入失败后 SQL 不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12962400/

相关文章:

nhibernate - FluentNHibernate 或端口到 NHibernate 的代码映射

nhibernate - 如何强制 RIA 服务在一种查询方法中包含子实体而不在另一种方法中包含子实体

c# - 使用 SQL 查询中的条件查询串联从数据库中检索数据

c# - 绑定(bind) SelectedItem 与 SelectedIndex - 我应该什么时候选择一个而不是另一个?

C#4 : Real-World Example of Dynamic Types

c# - 使用委托(delegate)处理错误

.net - 为什么此查询返回的记录集的状态为 "closed"?

sql - 部分字符串匹配 SQL - 内连接

c# - 多态性、泛型和匿名类型 C#

node.js - 如何使用sequelize mssql Node.js从存储过程获取输出参数