немного дополню п.3
Alexey Kudinov для "клиентских" транзакций выполняется, как правило два доп. батча
на trans=conn.BeginTransaction();
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSACTION |
и на trans.Commit();
или на trans.Rollback();
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION |
в этом случае тебе дается возможность на клиенте проанализировать результат (сделать обработку данных "привычными" средствыми) выполнения операций, которые ты включаешь в транзакцию, в совокупности с другими данными своей программы и принять решение на Commit или Rollback транзакции.
это более гибкое управление, т.к. есть возможность чисто программно выполнять различные последовательности запросов в рамках одной транзакции и принимать решения по совокупности данных, связанных не только с SQL сервером, но и другими данными.
---
если принятие решений делается по принципу - была ошибка, то откатить транзакцию (как в твоем примере) - в этом случае проще и быстрее выполнить "серверную" транзакцию.