Trying to detect a rollback condition when there are two or more statements involved. For SqlCommand.ExecuteNonQuery
Method, The docs says
If no statements are detected that contribute to the count, the return value is -1. If a rollback occurs, the return value is also -1.
I'm inserting -1
on purpose as an invalid entry in the referenced table having referential integrity constraints.
string sql = $@"
BEGIN TRANSACTION
BEGIN TRY
DELETE FROM CustomerContact WHERE CustomerId = @Id
INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Connection.Open();
command.Parameters.Add("Id", SqlDbType.Int).Value = id;
int result = command.ExecuteNonQuery();
Console.WriteLine(result); // -> returns affected deleted rows but not -1
}
Rollback is working as expected but I'm not getting the -1
from ExecuteNonQuery
, instead, I get a number of affected rows from the DELETE
operation ( the first statement )
I did use SqlTransaction
earlier but I'm testing out the behavior of embedded SQL based transactions.
I suggest you just throw in the CATCH
block to indicate an error and corresponding rollback occurred rather than try to detect the ROLLBACK
itself.
It's a good practice to specify SET XACT_ABORT ON;
with T-SQL transactions to ensure the transaction is rolled back immediately in the case of a timeout. This is because timeouts occur on the client side, where the API cancels the running query and prevents the CATCH block with the ROLLBACK
from executing. The connection then gets returned to the pool with the open transaction and the locks are not yet released. Although the transaction will be eventually get rolled back when the pooled connection is reused/reset or closed, the XACT_ABORT setting will cause that to occur immediately and release resource locks.
Below is the T-SQL transaction management and structured error handling pattern I recommend for most situations. Also, note the liberal use of semi-colons to avoid surprises .
string sql = $@"
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM CustomerContact WHERE CustomerId = @Id;
INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
THROW;
END CATCH";
try
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Connection.Open();
command.Parameters.Add("Id", SqlDbType.Int).Value = id;
int result = command.ExecuteNonQuery();
Console.WriteLine(result); // -> returns affected deleted rows but not -1
}
}
catch
{
Console.WriteLine('handle exception here');
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.