sql server - framework - Refactorización ADO.NET-SqlTransaction vs. TransactionScope
transactionscope vb (6)
He "heredado" un pequeño método C # que crea un objeto ADO.NET SqlCommand y repite una lista de elementos para guardar en la base de datos (SQL Server 2005).
En este momento, se utiliza el enfoque tradicional SqlConnection / SqlCommand, y para asegurarse de que todo funcione, los dos pasos (eliminar las entradas antiguas y luego insertar las nuevas) se envuelven en una Transacción Sql de ADO.NET.
using (SqlConnection _con = new SqlConnection(_connectionString))
{
using (SqlTransaction _tran = _con.BeginTransaction())
{
try
{
SqlCommand _deleteOld = new SqlCommand(......., _con);
_deleteOld.Transaction = _tran;
_deleteOld.Parameters.AddWithValue("@ID", 5);
_con.Open();
_deleteOld.ExecuteNonQuery();
SqlCommand _insertCmd = new SqlCommand(......, _con);
_insertCmd.Transaction = _tran;
// add parameters to _insertCmd
foreach (Item item in listOfItem)
{
_insertCmd.ExecuteNonQuery();
}
_tran.Commit();
_con.Close();
}
catch (Exception ex)
{
// log exception
_tran.Rollback();
throw;
}
}
}
Ahora, he estado leyendo mucho sobre la clase TransactionScope .NET últimamente, y me preguntaba, ¿cuál es el enfoque preferido aquí? ¿Ganaría algo (legibilidad, velocidad, confiabilidad) cambiando a usar
using (TransactionScope _scope = new TransactionScope())
{
using (SqlConnection _con = new SqlConnection(_connectionString))
{
....
}
_scope.Complete();
}
¿Qué preferirías y por qué?
Bagazo
Microsoft recomienda usar el alcance de la transacción:
http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
La idea básica es que el alcance de la transacción administrará el "contexto de transacción ambiental" para usted. Comienza hablando con una base de datos, tiene una transacción de SQL, luego habla con la base de datos número 2 y la transacción se eleva a una transacción distribuida.
El alcance de la transacción funciona para usted, por lo que puede concentrarse en la funcionalidad del sistema, en lugar de la plomería.
EDITAR
Cuando utiliza un ámbito de transacción, todo lo que se encuentra dentro de ese ámbito está cubierto por la transacción. Por lo tanto, guarda una línea de código, donde conecta el comando a la transacción. Esta es una posible fuente de error, por ejemplo, si hubiera una posibilidad en 1000 de que esta línea hubiera sido olvidada, ¿cuántos perdería?
Editar 2
De acuerdo con el comentario sobre Triynko a continuación. Sin embargo, utilizamos Entity Framework, EF cerrará automáticamente y volverá a abrir una conexión para enlistarla en una transacción. No cierra físicamente la conexión de forma similar, la libera al grupo de conexiones y obtiene una nueva, que puede ser la misma o puede ser diferente.
No ganará nada de inmediato al cambiar su código existente para usar TransactionScope
. Debe usarlo para el desarrollo futuro debido a la flexibilidad que proporciona. En el futuro, será más fácil incluir cosas que no sean llamadas ADO.NET en una transacción.
Por cierto, en su ejemplo publicado, las instancias de SqlCommand
deberían estar en el using
bloques.
Ok, tal vez sea demasiado tarde para esto ... pero de todos modos, lo escribiré para aquellos interesados ...
Ya que tengo una mejor imagen ahora, después de tener muchas dificultades con mi enfoque actual basado en SqlTransaction
que podría cambiar en favor de TransactionScope
, como lo veo ... la principal ventaja de TransactionScope
es que se puede usar muy fácilmente en el Capa de negocios .
Prefiero TransactionScope. No funciona perfectamente en todos los escenarios, pero en el que usted describe, es la mejor solución.
Mi razonamiento:
- El alistamiento en la transacción es automático
- La reversión de transacciones en el caso de una excepción es automática
Juntos, el resultado es un poco menos de código y un diseño generalmente más robusto, ya que el sistema está manejando algunos de los detalles para mí; Es una cosa menos que debo recordar hacer.
Además, la inscripción de Transacción transparente puede ser particularmente útil cuando tiene varios métodos anidados en su DAL, aunque debe tener cuidado de que su transacción no se convierta en una distribuida que requiera el DTC, lo que puede suceder si utiliza múltiples SqlConnections, incluso si apuntan a la misma base de datos.
Solo tenga en cuenta que usar Transaction Scope a veces tendremos muchos problemas porque muchas de las configuraciones que debemos realizar en el Servidor, como la configuración de DTC, Firewall y etc. Por lo tanto, recomendé el uso de SqlTransaction más en la implementación.
También tarde ... Puede tener transacciones "anidadas" fácilmente en la capa empresarial incluso si la base de datos no admite transacciones anidadas. .NET controla el anidamiento y termina usando una transacción de base de datos (al menos en el caso de SQL Server 2008+). Esto hace que sea mucho más fácil reutilizar el código de acceso a datos fuera de su intención original, como parte de una transacción más grande.