回滚后返回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结果都受触发器的影响。