La forma más limpia de usar BeginTransaction usando try catch

Jan 27 2021

Hasta ahora estoy usando dos bloques try catch para mis consultas. El primero arrojará un error si no se establece la conexión. El segundo comprueba si SqlCommandse ejecuta correctamente. Como el siguiente ejemplo

try
{
  using(varconnection=newSqlConnection())
  using(varcmd=newSqlCommand())
  {
  
    connection.Open();
    var transaction=connection.BeginTransaction();
    cmd.Connection=connection;
    cmd.Transaction=transaction;

    try
    {
     cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
     cmd.ExecuteNonQuery();

     cmd.CommandText="InsertintoCustomers(Name)values('George')";
     cmd.ExecuteNonQuery();

     transaction.Commit();
   }
   catch
   {
     try{transaction.Rollback();}catch{}
   }
  }
}
catch
{

}

Encontré un segundo ejemplo que me parece más claro.

SqlTransactiontransaction=null;
using(varconnection=newSqlConnection())
using(varcmd=newSqlCommand())
{
   try
   {
   connection.Open();
   transaction=connection.BeginTransaction();
   cmd.Connection=connection;
   cmd.Transaction=transaction;

   cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
   cmd.ExecuteNonQuery();

   cmd.CommandText="InsertintoCustomers(Name)values('George')";
   cmd.ExecuteNonQuery();

   transaction.Commit();
   transaction.Dispose();
   transaction=null;
}
catch
{
   if(transaction!=null)
   {
      try{transaction.Rollback();}catch{}
   }
 }
}

¿Ambos tienen el mismo resultado? ¿Cuál de los dos es más preferible?

Respuestas

2 Charlieface Jan 28 2021 at 00:18

Ninguno de esos dos métodos es bueno. Son demasiado prolijos.

El mejor método es simplemente poner el Transactionen a usingtambién, también debemos usar un parámetro para la consulta:

using(var connection = new SqlConnection(connString))
using(var cmd = new SqlCommand("Insert into Customers (Name) values (@Name));"))
{
    var param = cmd.Parameters.Add("@Name", SqlDbType.VarChar, insert_column_length_here);
    connection.Open();
    using(var transaction = connection.BeginTransaction())
    {
        cmd.Transaction = transaction;
        param.Value = "Dimitri";
        cmd.ExecuteNonQuery();

        param.Value = "George";
        cmd.ExecuteNonQuery();

        transaction.Commit();
    }
}

Podemos ver que la eliminación del objeto de transacción se revertirá automáticamente si aún no se ha confirmado, mirando el código fuente . Así usingque limpiará todo.

Si necesita capturar para mostrar un mensaje al usuario, hágalo fuera del código, es decir, coloque un try/catchalrededor de todo. No hagas el código de limpieza tú mismo