Обрабатывать транзакцию при вызове хранимой процедуры SQL в цикле side A C#



Я работаю над системой, которая уже разработана некоторыми другими разработчиками.
И в этой системе они вызвали хранимую процедуру, которая используется для вставки записей в боковой цикл в C# без использования пользовательских типов таблиц.



И что мне нужно сделать, так это добавить транзакцию в этот сценарий. Но проблема в том, что я понятия не имею о месте проведения сделки.



Я хотел бы знать, есть ли он в коде C#, деформирующем цикл, или внутри хранимой процедуры.

684   3  

3 ответов:

Вы можете иметь его только внутри цикла C#. Транзакция, запущенная внутри процедуры , должна быть зафиксирована до завершения процедуры. SQL Server проверяет @@TRANCOUNT до и после выполнения процедуры, а также если результаты не совпадают, возникает исключение. Таким образом, процедура не может начать транзакцию, которая должна быть зафиксирована вызывающей стороной.

Проще всего обернуть код C# в область транзакций:

using(var scope =  new TransactionScope(
      TransactionScopeOption.Required, 
      new TransactionOptions() {
         IsolationLevel = IsolationLevel.ReadCommitted
      })) {
   // Do the work here
   scope.Complete();
}

Обратите внимание, что передача IsolationLevel = IsolationLevel.ReadCommitted является критический.

В этом случае транзакция должна начинаться в коде C#, у вас есть следующие опции:

  • Используйте Transaction из 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 (Implicite) Ambient transaction (при исключении это автоматический откат)

    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();
    } 
    
    • Использование CommittableTransaction (явная) внешняя транзакция

      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;
       }          
      } 
      

Для Ambient transactions, пожалуйста, помните, что если вы откроете более одного соединения, то оно получит повышен с local to global transaction, таким образом, требуя MSDTC, и это оказывает влияние на производительность.

Проверьте следующую ссылку:

Http://www.codeproject.com/Articles/690136/All-About-TransactionScope

В 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

В C#

using(TransactionScope tran = new TransactionScope()) {

     // DO YOUR INSERT /UPDATE /DELETE HERE 

    tran.Complete();
}

Comments

    Ничего не найдено.