回滚后返回ExecuteNonQuery的值

时间:2013-02-25 15:36:26

标签: c# .net stored-procedures sqlclient

假设我们的存储过程确实如此:

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? 我仍然得到受影响的行数。文档说明"If a rollback occurs, the return value is also -1"

我在这里缺少什么?

1 个答案:

答案 0 :(得分: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结果都受触发器影响。