回滚后返回ExecuteNonQuery的值

假设我们有一个存储过程,它确实像这样:

BEGIN TRANSACTION UPDATE sometable SET aField = 0 WHERE anotherField = 1; UPDATE sometable SET aField = 1 WHERE anotherField = 2; ROLLBACK TRANSACTION; 

从C#我们有这样的事情:

 using (var connection = new SqlConnection("connection string")) { connection.Open(); var cmd = connection.CreateCommand(); cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "my_procedure"; var res = cmd.ExecuteNonQuery(); } 

为什么我没有得到res == -1? 我仍然得到受影响的行数。 当文档声明“如果发生回滚,返回值也为-1”

我在这里缺少什么?

似乎ExecuteNonQuery的返回值不受回滚的影响,即使文档清楚地说明了这一点。 以下是一些可能的解决方法。

1)使用ExecuteScalar

SP:

 DECLARE @RowCount INT DECLARE @Error INT BEGIN TRAN UPDATE Table1 SET Value1 = NULL SELECT @RowCount = @@ROWCOUNT, @Error = @@ERROR IF @Error <> 0 BEGIN ROLLBACK TRAN SELECT -1 END ELSE BEGIN COMMIT TRAN SELECT @RowCount END 

C#

 using (SqlConnection dbConnection = new SqlConnection("Data Source=.;Initial Catalog=Database1;Integrated Security=True;MultipleActiveResultSets=True")) { dbConnection.Open(); using (SqlCommand command = dbConnection.CreateCommand()) { command.CommandText = "QuickTest"; command.CommandType = CommandType.StoredProcedure; rowsAffected = command.ExecuteScalar(); } } 

2)使用返回/输出参数

SP: DECLARE @RowCount INT DECLARE @Error INT

 BEGIN TRAN UPDATE Table1 SET Value1 = NULL SELECT @RowCount = @@ROWCOUNT, @Error = @@ERROR IF @Error <> 0 BEGIN ROLLBACK TRAN RETURN -1 END ELSE BEGIN COMMIT TRAN RETURN @RowCount END 

C#

 using (SqlConnection dbConnection = new SqlConnection("Data Source=.;Initial Catalog=Database1;Integrated Security=True;MultipleActiveResultSets=True")) { dbConnection.Open(); using (SqlCommand command = dbConnection.CreateCommand()) { command.Parameters.Add(new SqlParameter() {Direction = ParameterDirection.ReturnValue }); command.CommandText = "QuickTest"; command.CommandType = CommandType.StoredProcedure; command.ExecuteNonQuery(); rowsAffected = command.Parameters[0].Value; } } 

3)将回滚/提交逻辑移动到代码中

这将使您能够确定是否发生回滚,并在必要时输出值-1。 需要从sproc中删除事务语句。

SP:

 UPDATE Table1 SET Value1 = NULL 

C#:

 using (SqlConnection dbConnection = new SqlConnection("Data Source=.;Initial Catalog=Database1;Integrated Security=True;MultipleActiveResultSets=True")) { dbConnection.Open(); using (SqlTransaction tran = dbConnection.BeginTransaction()) { using (SqlCommand command = dbConnection.CreateCommand()) { command.Transaction = tran; try { command.Parameters.Add(new SqlParameter() {Direction = ParameterDirection.ReturnValue }); command.CommandText = "QuickTest"; command.CommandType = CommandType.StoredProcedure; rowsAffected = command.ExecuteNonQuery(); } catch (Exception) { rowsAffected = -1; throw; } tran.Commit(); } } } 

如前所述,@@ ROWCOUNT值和ExecuteNonQuery结果都受触发器的影响。