I have a stored procedure which is updating multiple tables in SQL Server. This procedure is being used from C# code.
If I apply the transaction only in C# code would it be a good practice?
Do I need to apply transaction in both C# code and stored procedure?
Thanks
Transactions that span multiple statements leave locks that hurt concurrency. So "always" creating a transactions is not a good idea. You should balance the cost against the benefit. "A SQL statement always runs in a transaction".
You use transactions when the set of database operations you are making needs to be atomic. That is - they all need to succeed or fail. Nothing in between. Transactions are to be used to ensure that the database is always in a consistent state.
A transaction is a unit of work that is performed against a database. Transactions are units or sequences of work accomplished in a logical order, whether in a manual fashion by a user or automatically by some sort of a database program. A transaction is the propagation of one or more changes to the database.
Database transaction takes a database from one consistent state to another. At the end of the transaction the system must be in the prior state if the transaction fails or the status of the system should reflect the successful completion if the transaction goes through. It is a single unit of work.
If the process is only calling a single stored procedure in a single SqlCommand
, then just handle the transaction inside the stored procedure and there is no need to manage it from the C# code. You would only need to manage it in the C# code in order to maintain the transaction across multiple SqlCommand
executions.
FYI, managing the transaction in both layers is only necessary if both of the following are true:
SqlCommand
calls that need to be considered a single operationOutside of the above scenario, managing the transaction in both layers is pointless as there is only a single transaction. If the transaction is started in the C# code, then all that happens in the stored procedure when BEGIN TRAN
is called is that @@TRANCOUNT
is incremented. And the transaction is not truly committed until the @@TRANCOUNT
comes back down to 0 by issuing the same number of COMMIT
s as shown in @@TRANCOUNT
(in this case, issuing a COMMIT
in the stored procedure and again in the C# code, at which point SQL Server actually does the real "commit"). However, a single ROLLBACK
brings @@TRANCOUNT
back to 0 no matter what number it was at. And if that happens in the Stored Proc, you cannot issue either a COMMIT
or ROLLBACK
in the C# code as the transaction no longer exists, so you would need to test for an active transaction first.
Assuming that you are using at least SQL Server 2005, if not newer, be sure to use the T-SQL TRY / CATCH
syntax to manage the COMMIT / ROLLBACK
within the stored procedure. You will need the TRY / CATCH syntax to properly catch errors and exit the proc(s) even if you are only managing the transaction in the C# code.
For example:
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With