Je suis intéressé par les effets secondaires et les problèmes potentiels du schéma suivant :
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
D'après ce que j'ai compris, ce modèle est valable lorsqu'il est utilisé avec une seule procédure - la procédure achèvera toutes ses déclarations sans erreur, ou bien elle annulera toutes les actions et signalera l'erreur.
Cependant, lorsqu'une procédure stockée appelle une autre procédure stockée pour effectuer une sous-unité de travail (étant entendu que la plus petite procédure est parfois appelée seule), je vois apparaître un problème lié aux rollbacks - un message d'information (niveau 16) est émis, indiquant que The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
. Je suppose que c'est parce que le retour en arrière dans la sous-procédure revient toujours sur la transaction la plus externe, et pas seulement sur la transaction lancée dans la sous-procédure.
Je veux que l'ensemble de la transaction soit annulée et interrompue en cas d'erreur (et que l'erreur soit signalée au client comme une erreur SQL), mais je ne suis pas sûr de tous les effets secondaires qui découlent du fait que les couches externes essaient d'annuler une transaction qui a déjà été annulée. Peut-être qu'une vérification de @@TRANCOUNT
avant de faire un retour en arrière à chaque couche TRY CATCH ?
Enfin, il y a le côté client (Linq2SQL), qui possède sa propre couche de transaction :
try
{
var context = new MyDataContext();
using (var transaction = new TransactionScope())
{
// Some Linq stuff
context.SubmitChanges();
context.MyStoredProcedure();
transactionComplete();
}
}
catch
{
// An error occured!
}
Dans le cas où une procédure stockée, "MySubProcedure", appelée à l'intérieur de MyStoredProcedure lève une erreur, puis-je être sûr que tout ce qui a été fait précédemment dans MyStoredProcedure sera annulé, que toutes les opérations Linq effectuées par SubmitChanges seront annulées, et enfin que l'erreur sera enregistrée ? Ou bien, que dois-je changer dans mon modèle pour garantir que l'ensemble de l'opération est atomique, tout en permettant aux parties enfants d'être utilisées individuellement (c'est-à-dire que les sous-procédures devraient toujours avoir la même protection atomique) ?