I'm working on a system which is already developed by some other developers. And in that system they have invoked a stored procedure which use to insert records in side a loop in C# without using User define table types.
And what I need to do is to add a transaction to this scenario. But the problem is I have no idea about the place to have the transaction.
I would like to know whether have it in the C# code warping up the loop or inside the stored procedure.
You can only have it inside the C# loop. A transaction started inside the procedure must commit before the procedures exits. SQL Server checks the @@TRANCOUNT
before and after running a procedure and if the results don't match an exception is raised. So is impossible for a procedure to start a transaction that has to be committed by caller.
The easiest think to do is to wrap your C# code in a transaction scope:
using(var scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions() {
IsolationLevel = IsolationLevel.ReadCommitted
})) {
// Do the work here
scope.Complete();
}
Note that passing the IsolationLevel = IsolationLevel.ReadCommitted
is critical .
In this case Transaction needs to begin in the C# code, you have following options:
Use the Transaction
from the Connection object
:
using (var conn = new SqlConnection(connString)) { conn.Open(); using (IDbTransaction tran = conn.BeginTransaction()) { try { // transactional code... using (SqlCommand cmd = conn.CreateCommand()) { // Loop the Insert operation here cmd.CommandText = "INSERT Operation"; cmd.Transaction = tran as SqlTransaction; cmd.ExecuteNonQuery(); } tran.Commit(); } catch(Exception ex) { tran.Rollback(); throw; } } }
Implicit or Explicit Ambient transaction
Use TransactionScope
(Implicit) Ambient transaction (On Exception it's an automatic rollback)
using (var scope = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted })) { using (var conn = new SqlConnection(connString)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { // Loop the Insert operation here cmd.CommandText = "INSERT Operation"; cmd.ExecuteNonQuery(); } } scope.Complete(); }
Use CommittableTransaction
(Explicit) Ambient transaction
var tran = new CommittableTransaction(); using (var conn = new SqlConnection(connString)) { conn.Open(); try { conn.EnlistTransaction(tran); using (SqlCommand cmd = conn.CreateCommand()) { // Loop the Insert operation here cmd.CommandText = "INSERT Operation"; cmd.ExecuteNonQuery(); } tran.Commit(); } catch(Exception ex) { tran.Rollback(); throw; } }
For Ambient transactions
, please remember that if you open more than one connection, then it will get promoted from local to global transaction
, thus requiring MSDTC
and that has a performance impact.
Check the following link:
http://www.codeproject.com/Articles/690136/All-About-TransactionScope
In SQL SERVER
BEGIN TRY
BEGIN TRAN
-- DO YOUR INSERT /UPDATE /DELETE HERE
COMMIT TRAN T1
END TRY
BEGIN CATCH
-- // ROLL BACK IF ERROR OCCURS
ROLLBACK TRAN T1
END CATCH
In C#
using(TransactionScope tran = new TransactionScope()) {
// DO YOUR INSERT /UPDATE /DELETE HERE
tran.Complete();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.