Se il processo è solo chiamando un singolo stored procedure in un unico SqlCommand
, poi basta gestire la transazione all'interno della stored procedure e non v'è alcuna necessità di gestirlo dal codice C#. Dovresti solo gestirlo nel codice C# per mantenere la transazione su più esecuzioni SqlCommand
.
FYI, gestire l'operazione in entrambi i livelli è necessario solo se entrambe le seguenti sono vere:
- il codice C# sta facendo più
SqlCommand
chiamate che devono essere considerati una singola operazione
- la stored le procedure possono/devono essere richiamate al di fuori di questo codice C#, ad esempio da altre stored procedure (nel qual caso potrebbe non esserci una Transazione esistente nel momento in cui le stored procedure sono/sono chiamate.
Esterno o Se lo scenario sopra descritto, la gestione della transazione in entrambi gli strati è inutile in quanto esiste una sola transazione. Se la transazione viene avviata nel codice C#, tutto ciò che accade nella stored procedure quando viene chiamato BEGIN TRAN
è che viene incrementato @@TRANCOUNT
. E la transazione non viene realmente impegnata fino a quando lo @@TRANCOUNT
torna indietro a 0 emettendo lo stesso numero di s come mostrato in @@TRANCOUNT
(in questo caso, emettendo uno COMMIT
nella stored procedure e nuovamente nel codice C#, in quale punto SQL Il server effettivamente fa il vero "commit"). Tuttavia, un singolo ROLLBACK
riporta @@TRANCOUNT
su 0 indipendentemente dal numero a cui era. E se ciò accade nella Proc. Memorizzata, non è possibile emettere uno COMMIT
o ROLLBACK
nel codice C# poiché la transazione non esiste più, quindi è necessario prima verificare una transazione attiva.
Supponendo che si stia utilizzando almeno SQL Server 2005, se non più recente, assicurarsi di utilizzare la sintassi T-SQL TRY/CATCH
per gestire lo COMMIT/ROLLBACK
all'interno della stored procedure. Avrete bisogno della sintassi TRY/CATCH per catturare correttamente gli errori ed uscire dal proc (s) anche se si sta gestendo solo la transazione nel codice C#.
Ad esempio:
BEGIN TRY
BEGIN TRAN;
UPDATE Table1 ... ;
UPDATE Table2 ... ;
UPDATE Table3 ... ;
COMMIT TRAN;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRAN;
END;
THROW; -- if using SQL Server 2012 or newer, else use RAISERROR
END CATCH;
fonte
2014-09-13 05:33:03
Oh dio, le transazioni di SQL Server nidificate .. evitare come la peste. Almeno i trigger non sono coinvolti. Questa è una delle poche aree in cui avrei dato un calcio a uno sviluppatore di SQL Server, se ne avesse la possibilità. – user2864740
Grazie mille ... Sto eseguendo più SqlCommand e ogni comando sta aggiornando più tabelle utilizzando proc in Sql Server 2008 R2, quindi in tal caso se utilizzo Transaction solo a livello di codice C#, funzionerebbe correttamente? –
@AbhishekSrivastava: controlla la mia risposta aggiornata come ho affrontato tale scenario mentre devi aver aggiunto il commento ;-). Tutto dipende dal fatto che le Stored Procedures possano essere richiamate da altre Stored Procedures o individualmente da un altro codice C# che potrebbe non essere incluso in una transazione. –