Меня интересуют побочные эффекты и потенциальные проблемы следующего шаблона:
CREATE PROCEDURE [Name]
AS
BEGIN
BEGIN TRANSACTION
BEGIN TRY
[...Perform work, call nested procedures...]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
END
Насколько я понимаю, этот шаблон является правильным при использовании с одной процедурой - процедура либо завершит все свои утверждения без ошибок, либо откатит все действия и сообщит об ошибке.
Однако, когда одна хранимая процедура вызывает другую хранимую процедуру для выполнения некоторого подразделения (при том понимании, что меньшая процедура иногда вызывается сама по себе), я вижу проблему, связанную с откатами - информационное сообщение ( Уровень 16) выдается с указанием The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
. Я полагаю, это связано с тем, что откат в подпроцедуре всегда выполняет откат самой внешней транзакции, а не только транзакции, запущенной в подпроцедуре.
Я хочу, чтобы все было откатано и прервано, если возникнет какая-либо ошибка (и ошибка будет сообщена клиенту как ошибка SQL), я просто не уверен во всех побочных эффектах, которые исходят от внешних слоев, пытающихся откат транзакции, которая уже была откатана. Возможно, проверка @@TRANCOUNT
перед выполнением отката на каждом слое TRY CATCH?
Наконец, есть клиентская часть (Linq2SQL), которая имеет собственный уровень транзакций:
try
{
var context = new MyDataContext();
using (var transaction = new TransactionScope())
{
// Some Linq stuff
context.SubmitChanges();
context.MyStoredProcedure();
transactionComplete();
}
}
catch
{
// An error occured!
}
В случае, если хранимая процедура «MySubProcedure» с именем внутри MyStoredProcedure вызывает ошибку, могу ли я быть уверен, что все ранее выполненное в MyStoredProcedure будет откатано, все операции Linq, выполненные SubmitChanges будет откат, и наконец, что ошибка будет зарегистрирована? Или что мне нужно изменить в моем шаблоне, чтобы гарантировать, что вся операция является атомарной, при этом позволяя дочерним деталям использоваться индивидуально (то есть подпроцедуры должны иметь такую же атомную защиту)