0

I am working on distriuted transactions on Oracle databases.

I have the following code, see below and 2 questions. targetConnection and sourceConnection are both Oracle databases and are located on different networks.

1) Which of the command will be commited first, when the "Complete" method is called?

2) What will happen when one of the connections is lost during the "Complete" method? For example: Complete method is reached and targetCommand is commited, but now the connection to the sourceConnection is lost. In my case the whole scope should be rolled back because the sourceCommand cannot be commited.

private bool MergeRowNew(String mergeStmt, Dictionary<string, object> row, ColumnList columns)
      {
         bool result = false;
         bool targetTransaction = false;
         bool sourceTransaction = false;
         String mergeStmt2 = "merge into ...";
         Exception exception = null;

         using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,
            new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
         {

            try
            {
               //Using target connection
               using (OracleConnection targetConnection = new OracleConnection(this.target.ConnectionString))
               {
                  targetConnection.Open();
                  //Create new command for target
                  using (var targetCommand = targetConnection.CreateCommand(mergeStmt))
                  {
                     //Add parameters to target command
                     foreach (Column col in columns)
                     {
                        targetCommand.Parameters.Add(col.Name, row[col.Name]);
                     }
                     //Affected rows paramaeter
                     var rowCount = targetCommand.Parameters.Add(":numRows", OracleDbType.Integer, ParameterDirection.Output);
                     //execute insert in target db
                     targetCommand.ExecuteNonQuery();
                     //command succssesful when only one row was affected
                     if (Convert.ToInt32(rowCount.Value) == 1)
                     {
                        targetTransaction = true;
                     }
                  }

               }

               //If target transaction was succssesful then start the local transaction
               if (targetTransaction)
               {
                  //Using source connection
                  using (OracleConnection sourceConnection = new OracleConnection(this.source.ConnectionString))
                  {
                     sourceConnection.Open();
                     using (var sourceCommand = sourceConnection.CreateCommand(mergeStmt2))
                     {
                        sourceCommand.Parameters.Add("...","...");

                        var sourceRowcount = sourceCommand.Parameters.Add(":numRows", OracleDbType.Integer, ParameterDirection.Output);
                        sourceCommand.ExecuteNonQuery();
                        //command succssesful when only one row was affected
                        if (Convert.ToInt32(sourceRowcount.Value) == 1)
                        {
                           sourceTransaction = true;
                        }
                     }
                  }
               }
            }
            catch (Exception ex)
            {
               exception = ex;
            }
            //if both commands were succssesful then complete the scope
            if (targetTransaction && sourceTransaction)
            {
               scope.Complete();
               result = true;
            }
         } //End scope.

         //There was an exception. 
         if (exception != null)
         {
            //Do some logging.
         }

         return result;
      }
Zar
  • 11
  • 1
  • 3

1 Answers1

0

1) both commands will be committed simultaneously

2) the whole scope should be rolled back if any of enlisted connections fails

Devart
  • 119,203
  • 23
  • 166
  • 186