Я предлагаю вам просто вставить блок CATCH
, чтобы указать на ошибку и произошел соответствующий откат, а не пытаться обнаружить сам ROLLBACK
.
Рекомендуется указывать SET XACT_ABORT ON;
для транзакций T-SQL, чтобы обеспечить немедленный откат транзакции в случае тайм-аута. Это связано с тем, что тайм-ауты происходят на стороне клиента, где API отменяет запущенный запрос и предотвращает выполнение блока CATCH с ROLLBACK
. Затем соединение возвращается в пул с открытой транзакцией, и блокировки еще не сняты. Хотя транзакция будет в конечном итоге откатываться при повторном использовании / сбросе или закрытии пулированного соединения, настройка XACT_ABORT приведет к тому, что это произойдет немедленно, и снимет блокировки ресурсов.
Ниже приведено управление транзакциями T-SQL и его структурашаблон обработки ошибок, который я рекомендую для большинства ситуаций. Также обратите внимание на либеральное использование точек с запятой для избежания неожиданностей .
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');
}