La forma más limpia de usar BeginTransaction usando try catch
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 SqlCommand
se 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
Ninguno de esos dos métodos es bueno. Son demasiado prolijos.
El mejor método es simplemente poner el Transaction
en a using
tambié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í using
que limpiará todo.
Si necesita capturar para mostrar un mensaje al usuario, hágalo fuera del código, es decir, coloque un try/catch
alrededor de todo. No hagas el código de limpieza tú mismo