.NET Framework versión 2.0 incluye un nuevo marco de transacciones, accesible a través del espacio de nombres System.Transactions. Este marco expone las transacciones de tal forma que se integra completamente en .NET Framework, incluyendo ADO.NET.
Además de las mejoras de programabilidad, System.Transactions y ADO.NET pueden funcionar juntos para coordinar las optimizaciones al trabajar con transacciones. Una transacción promocionada es una transacción ligera (local) que, en caso necesario, se puede promover automáticamente a una transacción completamente distribuida.
En ADO.NET 2.0, System.Data.SqlClient agrega compatibilidad con transacciones promocionadas al trabajar con SQL Server 2005. Las transacciones promocionadas no invocan la sobrecarga adicional de las transacciones distribuidas, a menos que sea necesario, y son automáticas, es decir, no necesitan que intervenga el programador.
Solamente están disponibles cuando se utiliza el proveedor de datos de .NET Framework para SQL Server (SqlClient) con SQL Server 2005.
Creación de transacciones promocionadas
El proveedor de .NET Framework para SQL Server ofrece compatibilidad con transacciones promocionadas, que se gestionan a través de las clases del espacio de nombres System.Transactions de .NET Framework. Las transacciones promocionadas optimizan las transacciones distribuidas al aplazar la creación de las mismas hasta que es necesario. Si sólo se necesita un administrador de recursos, no tiene lugar ninguna transacción distribuida.
Situaciones de uso de transacciones promocionadas
Normalmente, las transacciones distribuidas consumen muchos recursos del sistema, siendo el encargado de administrarlas el Coordinador de transacciones distribuidas de Microsoft (MS DTC), que integra todos los administradores de recursos a los que se tiene acceso en la transacción. Una transacción promocionada es una forma especial de transacción System.Transactions que delega con efectividad el trabajo en una transacción SQL Server 2005 simple. System.Transactions, System.Data.SqlClient y SQL Server 2005 coordinan el trabajo que supone gestionar la transacción y promoverla a una transacción completamente distribuida cuando es necesario.
La ventaja de utilizar transacciones promocionadas es que cuando se abre una conexión con una transacción TransactionScope activa, y no hay ninguna otra conexión abierta, la transacción se confirma como una transacción ligera, en lugar de incurrir en la sobrecarga adicional de una transacción completamente distribuida.
Nota |
|---|
| La propiedad ConnectionString admite una palabra clave, Enlist, que indica si System.Data.SqlClient detectará contextos transaccionales e inscribirá automáticamente la conexión en una transacción distribuida. Si Enlist=true, la conexión se inscribe automáticamente en el contexto de transacción actual del subproceso de apertura. Si Enlist=false, la conexión SqlClient no interactúa con una transacción distribuida. El valor predeterminado de Enlist es true. Si no se especifica Enlist en la cadena de conexión, la conexión se inscribe automáticamente en una transacción distribuida si se detecta una en el momento de abrirse la conexión. |
Uso de TransactionScope
La clase TransactionScope crea un bloque de código transaccional al inscribir implícitamente las conexiones en una transacción distribuida. Debe llamar al método Complete al final del bloque TransactionScope antes de abandonarlo. Al salir del bloque se invoca el método Dispose. Si se ha producido una excepción que ocasiona que el código salga del ámbito, la transacción se considera anulada.
Se recomienda el uso de un bloque using para garantizar que se llama a Dispose en el objeto TransactionScope cuando se sale de dicho bloque. Si no se confirman ni deshacen las transacciones pendientes, el rendimiento puede verse seriamente afectado ya que el tiempo de espera predeterminado de TransactionScope es 1 minuto. Si no utiliza una instrucción using, todo el trabajo deberá realizarlo en un bloque Try y llamar explícitamente al método Dispose en el bloque Finally.
Si se produce una excepción en el TransactionScope, la transacción se marca como incoherente y se abandona. Se deshará cuando se elimine el TransactionScope. Si no se produce ninguna excepción, las transacciones participantes se confirman.
Nota |
|---|
| La clase TransactionScope crea una transacción con un IsolationLevel predeterminado de Serializable. Dependiendo de la aplicación, podría estudiar la posibilidad de reducir el nivel de aislamiento para evitar una elevada contención en la aplicación. |
Nota |
|---|
| Se recomienda que sólo realice actualizaciones, inserciones y eliminaciones en transacciones distribuidas, ya que consumen una cantidad considerable de recursos de base de datos. Las instrucciones SELECT podrían bloquear los recursos de base de datos de forma innecesaria, y en algunas situaciones, podría ser necesario utilizar transacciones para las selecciones. Todo el trabajo que no sea de base de datos debe realizarse fuera del ámbito de la transacción, a menos que estén implicados otros administradores de recursos de transacción. Aunque una excepción en el ámbito de la transacción impide que se confirme la misma, la clase TransactionScope no deja deshacer los cambios que haya realizado el código fuera del ámbito de la propia transacción. Si necesita realizar alguna acción cuando se deshaga la transacción, deberá escribir su propia implementación de la interfaz IEnlistmentNotification e inscribirla explícitamente en la transacción. |
Ejemplo
Trabajar con System.Transactions requiere que tenga una referencia a System.Transactions.dll.
El siguiente código demuestra cómo crear una transacción promocionada con respecto a dos instancias de SQL Server diferentes, representadas por dos objetos SqlConnection diferentes, que se incluyen en un bloque TransactionScope. El código crea el bloque TransactionScope con una instrucción using y abre la primera conexión, que automáticamente se inscribe en el TransactionScope. La transacción se inscribe inicialmente como una transacción ligera y no como una completamente distribuida. El código asume la existencia de lógica condicional que, para una mayor brevedad, se ha omitido, y abre la segunda conexión sólo si es necesario, que se inscribe en el TransactionScope. Cuando se abre la conexión, la transacción se promociona automáticamente a una transacción completamente distribuida. A continuación, el código invoca Complete, que confirma la transacción. El código elimina las dos conexiones al salir de las instrucciones using de las conexiones. Al término del bloque using de TransactionScope, se llama automáticamente al método Dispose de TransactionScope. Si en algún punto del bloque TransactionScope se ha producido una excepción, no se llamará a Complete y cuando se elimine el TransactionScope, se deshará la transacción distribuida.
Using transScope As New TransactionScope()
Using connection1 As New SqlConnection(connectString1)
' Opening connection1 automatically enlists it in the
' TransactionScope as a lightweight transaction.
connection1.Open()
' Do work in the first connection.
' Assumes conditional logic in place where the second
' connection will only be opened as needed.
Using connection2 As New SqlConnection(connectString2)
' Open the second connection, which enlists the
' second connection and promotes the transaction to
' a full distributed transaction.
connection2.Open()
' Do work in the second connection.
End Using
End Using
' Commit the transaction.
transScope.Complete()
End Using
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection connection1 = new
SqlConnection(connectString1))
{
// Opening connection1 automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Do work in the first connection.
// Assumes conditional logic in place where the second
// connection will only be opened as needed.
using (SqlConnection connection2 = new
SqlConnection(connectString2))
{
// Open the second connection, which enlists the
// second connection and promotes the transaction to
// a full distributed transaction.
connection2.Open();
// Do work in the second connection.
}
}
// The Complete method commits the transaction.
transScope.Complete();
}
Vea también