Implementar una transacción implícita mediante el ámbito de la transacciónImplementing an Implicit Transaction using Transaction Scope

La clase TransactionScope proporciona una manera simple de marcar un bloque de código como participar en una transacción, sin exigirle que interactuara con la propia transacción.The TransactionScope class provides a simple way to mark a block of code as participating in a transaction, without requiring you to interact with the transaction itself. Un ámbito de la transacción puede seleccionar y administrar automáticamente la transacción ambiente.A transaction scope can select and manage the ambient transaction automatically. Debido a su facilidad de uso y eficacia, se recomienda que utilice la clase TransactionScope al desarrollar una aplicación de transacción.Due to its ease of use and efficiency, it is recommended that you use the TransactionScope class when developing a transaction application.

Además, no necesita dar de alta explícitamente los recursos con la transacción.In addition, you do not need to enlist resources explicitly with the transaction. Cualquier administrador de recursos System.Transactions (como SQL Server 2005) puede detectar la existencia de una transacción ambiente creada por el ámbito y automáticamente darse de alta.Any System.Transactions resource manager (such as SQL Server 2005) can detect the existence of an ambient transaction created by the scope and automatically enlist.

Crear un ámbito de la transacciónCreating a transaction scope

En el ejemplo siguiente se muestra un uso sencillo de la clase TransactionScope.The following sample shows a simple usage of the TransactionScope class.

// This function takes arguments for 2 connection strings and commands to create a transaction 
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the 
// transaction is rolled back. To test this code, you can connect to two different databases 
// on the same server by altering the connection string, or to another 3rd party RDBMS by 
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
    string connectString1, string connectString2,
    string commandText1, string commandText2)
{
    // Initialize the return value to zero and create a StringWriter to display results.
    int returnValue = 0;
    System.IO.StringWriter writer = new System.IO.StringWriter();

    try
    {
        // Create the TransactionScope to execute the commands, guaranteeing
        // that both commands can commit or roll back as a single unit of work.
        using (TransactionScope scope = new TransactionScope())
        {
            using (SqlConnection connection1 = new SqlConnection(connectString1))
            {
                // Opening the connection automatically enlists it in the 
                // TransactionScope as a lightweight transaction.
                connection1.Open();

                // Create the SqlCommand object and execute the first command.
                SqlCommand command1 = new SqlCommand(commandText1, connection1);
                returnValue = command1.ExecuteNonQuery();
                writer.WriteLine("Rows to be affected by command1: {0}", returnValue);

                // If you get here, this means that command1 succeeded. By nesting
                // the using block for connection2 inside that of connection1, you
                // conserve server and network resources as connection2 is opened
                // only when there is a chance that the transaction can commit.   
                using (SqlConnection connection2 = new SqlConnection(connectString2))
                {
                    // The transaction is escalated to a full distributed
                    // transaction when connection2 is opened.
                    connection2.Open();

                    // Execute the second command in the second database.
                    returnValue = 0;
                    SqlCommand command2 = new SqlCommand(commandText2, connection2);
                    returnValue = command2.ExecuteNonQuery();
                    writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
                }
            }

            // The Complete method commits the transaction. If an exception has been thrown,
            // Complete is not  called and the transaction is rolled back.
            scope.Complete();

        }
       
    }
    catch (TransactionAbortedException ex)
    {
        writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
    }

    // Display messages.
    Console.WriteLine(writer.ToString());

    return returnValue;
}
'  This function takes arguments for 2 connection strings and commands to create a transaction 
'  involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the 
'  transaction is rolled back. To test this code, you can connect to two different databases 
'  on the same server by altering the connection string, or to another 3rd party RDBMS  
'  by altering the code in the connection2 code block.
Public Function CreateTransactionScope( _
  ByVal connectString1 As String, ByVal connectString2 As String, _
  ByVal commandText1 As String, ByVal commandText2 As String) As Integer

    ' Initialize the return value to zero and create a StringWriter to display results.
    Dim returnValue As Integer = 0
    Dim writer As System.IO.StringWriter = New System.IO.StringWriter

    Try
    ' Create the TransactionScope to execute the commands, guaranteeing
    '  that both commands can commit or roll back as a single unit of work.
        Using scope As New TransactionScope()
            Using connection1 As New SqlConnection(connectString1)
                ' Opening the connection automatically enlists it in the 
                ' TransactionScope as a lightweight transaction.
                connection1.Open()

                ' Create the SqlCommand object and execute the first command.
                Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
                returnValue = command1.ExecuteNonQuery()
                writer.WriteLine("Rows to be affected by command1: {0}", returnValue)

                ' If you get here, this means that command1 succeeded. By nesting
                ' the using block for connection2 inside that of connection1, you
                ' conserve server and network resources as connection2 is opened
                ' only when there is a chance that the transaction can commit.   
                Using connection2 As New SqlConnection(connectString2)
                    ' The transaction is escalated to a full distributed
                    ' transaction when connection2 is opened.
                    connection2.Open()

                    ' Execute the second command in the second database.
                    returnValue = 0
                    Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
                    returnValue = command2.ExecuteNonQuery()
                    writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
                End Using
            End Using

        ' The Complete method commits the transaction. If an exception has been thrown,
        ' Complete is called and the transaction is rolled back.
        scope.Complete()
        End Using
    Catch ex As TransactionAbortedException
        writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message)
    End Try

    ' Display messages.
    Console.WriteLine(writer.ToString())

    Return returnValue
End Function

El ambiente de transacción ha comenzado una vez que se ha creado un nuevo objeto TransactionScope .The transaction scope is started once you create a new TransactionScope object. Como se muestra en el ejemplo de código, se recomienda crear ámbitos con una mediante instrucción.As illustrated in the code sample, it is recommended that you create scopes with a using statement. El mediante instrucción está disponible tanto en C# y en Visual Basic y funciona como un try... finally bloque para asegurarse de que el ámbito se elimina correctamente.The using statement is available both in C# and in Visual Basic, and works like a try...finally block to ensure that the scope is disposed of properly.

Al crear una instancia de TransactionScope, el administrador de transacciones determina en qué transacción participar.When you instantiate TransactionScope, the transaction manager determines which transaction to participate in. Una vez determinado, el ámbito siempre participa en esa transacción.Once determined, the scope always participates in that transaction. La Decisión se basa en dos factores: si una transacción ambiente está presente y el valor de la TransactionScopeOption parámetro del constructor.The decision is based on two factors: whether an ambient transaction is present and the value of the TransactionScopeOption parameter in the constructor. La transacción ambiente es la transacción dentro de la que su código se ejecuta.The ambient transaction is the transaction within which your code executes. Puede obtener una referencia a la transacción ambiente llamando a la propiedad estática Transaction.Current de la clase Transaction.You can obtain a reference to the ambient transaction by calling the static Transaction.Current property of the Transaction class. Para obtener más información sobre cómo se utiliza este parámetro, vea el administración de flujo de transacciones con TransactionScopeOption sección de este tema.For more information on how this parameter is used, see the Managing transaction flow using TransactionScopeOption section of this topic.

Completar un ámbito de la transacciónCompleting a transaction scope

Cuando la aplicación termina todo el trabajo que tiene que llevar a cabo en una transacción, debe llamar al método Complete solo una vez para notificar al administrador de transacciones que la transacción se puede confirmar.When your application completes all the work it wants to perform in a transaction, you should call the Complete method only once to inform the transaction manager that it is acceptable to commit the transaction. Es muy recomendable colocar la llamada a Complete como la última instrucción del mediante bloque.It is very good practice to put the call to Complete as the last statement in the using block.

No se puede llamar a este método, anula la transacción, porque el Administrador de transacciones interpreta esto como un error del sistema, o equivalente a una excepción producida dentro del ámbito de la transacción.Failing to call this method aborts the transaction, because the transaction manager interprets this as a system failure, or equivalent to an exception thrown within the scope of the transaction. Sin embargo, llamar a este método no garantiza que se vaya a confirmar la transacción.However, calling this method does not guarantee that the transaction wil be committed. Es solo una manera de informar al administrador de transacciones de su estado.It is merely a way of informing the transaction manager of your status. Después de llamar a este métodoComplete ya no podrá obtener acceso a la transacción de ambiente mediante la propiedad Current y, si intenta hacerlo, se producirá una excepción.After calling the Complete method, you can no longer access the ambient transaction by using the Current property, and attempting to do so will result in an exception being thrown.

Si el TransactionScope objeto creó la transacción inicialmente, el trabajo real de confirmar la transacción por el Administrador de transacciones se produce después de la última línea de código en el mediante bloque.If the TransactionScope object created the transaction initially, the actual work of committing the transaction by the transaction manager occurs after the last line of code in the using block. Si no ha creado la transacción, se produce la confirmación cada vez que el propietario del objeto Commit llama al método CommittableTransaction.If it did not create the transaction, the commit occurs whenever Commit is called by the owner of the CommittableTransaction object. En ese momento en que el Administrador de transacciones llama administradores de los recursos y les informa a commit o rollback, en función de si el Complete se llamó al método en el TransactionScope objeto.At that point the transaction manager calls the resource managers and informs them to either commit or rollback, based on whether the Complete method was called on the TransactionScope object.

El mediante instrucción garantiza que el Dispose método de la TransactionScope se denomina objeto incluso si se produce una excepción.The using statement ensures that the Dispose method of the TransactionScope object is called even if an exception occurs. El método Dispose marca el fin del ámbito de la transacción.The Dispose method marks the end of the transaction scope. Las excepciones que se producen después de llamar a este método quizá no afecten a la transacción.Exceptions that occur after calling this method may not affect the transaction. Este método también restaura la transacción de ambiente a su estado previo.This method also restores the ambient transaction to it previous state.

Se inicia TransactionAbortedException si el ámbito crea la transacción, y ésta se anula.A TransactionAbortedException is thrown if the scope creates the transaction, and the transaction is aborted. Se inicia TransactionInDoubtException si el administrador de transacciones no puede llegar a una decisión de la confirmación.A TransactionInDoubtException is thrown if the transaction manager cannot reach a Commit decision. No se produce ninguna excepción si se confirma la transacción.No exception is thrown if the transaction is committed.

Deshacer una transacciónRolling back a transaction

Si desea revertir una transacción, no debería llamar al método Complete dentro del ámbito de la transacción.If you want to rollback a transaction, you should not call the Complete method within the transaction scope. Por ejemplo, puede producir una excepción dentro del ámbito.For example, you can throw an exception within the scope. Se deshará la transacción en la que participa.The transaction in which it participates in will be rolled back.

Administración de flujo de transacciones con TransactionScopeOptionManaging transaction flow using TransactionScopeOption

El ámbito de la transacción puede estar anidado al llamar a un método que utiliza desde dentro TransactionScope un método que utiliza su propio ámbito, como es el caso con el método RootMethod en el ejemplo siguiente,Transaction scope can be nested by calling a method that uses a TransactionScope from within a method that uses its own scope, as is the case with the RootMethod method in the following example,

void RootMethod()  
{  
     using(TransactionScope scope = new TransactionScope())  
     {  
          /* Perform transactional work here */  
          SomeMethod();  
          scope.Complete();  
     }  
}  
  
void SomeMethod()  
{  
     using(TransactionScope scope = new TransactionScope())  
     {  
          /* Perform transactional work here */  
          scope.Complete();  
     }  
}  

El ámbito de la transacción de nivel superior se conoce como el ámbito de la raíz.The top-most transaction scope is referred to as the root scope.

La clase TransactionScope proporciona varios constructores sobrecargados que aceptan una enumeración del tipo TransactionScopeOption, que define el comportamiento transaccional del ámbito.The TransactionScope class provides several overloaded constructors that accept an enumeration of the type TransactionScopeOption, which defines the transactional behavior of the scope.

Un objeto TransactionScope tiene tres opciones:A TransactionScope object has three options:

  • Unir la transacción ambiente o crear una nueva si no existe.Join the ambient transaction, or create a new one if one does not exist.

  • Ser un nuevo ámbito de la raíz, eso es, iniciar una nueva transacción y tener esa transacción siendo la nueva transacción ambiente dentro de su propio ámbito.Be a new root scope, that is, start a new transaction and have that transaction be the new ambient transaction inside its own scope.

  • No tomar parte en absoluto en una transacción.Not take part in a transaction at all. Como resultado, no hay ninguna transacción ambiente.There is no ambient transaction as a result.

Si se crean instancias del ámbito con Required, y una transacción ambiente está presente, el ámbito combina dicha transacción.If the scope is instantiated with Required, and an ambient transaction is present, the scope joins that transaction. Si, por otro lado, no hay ninguna transacción ambiente, a continuación, el ámbito crea una nueva transacción y se vuelve el ámbito de la raíz.If, on the other hand, there is no ambient transaction, then the scope creates a new transaction, and become the root scope. Este es el valor predeterminado.This is the default value. Cuando se utiliza Required, el código dentro del ámbito no necesita comportarse de manera diferente si es la raíz o simplemente uniendo la transacción ambiente.When Required is used, the code inside the scope does not need to behave differently whether it is the root or just joining the ambient transaction. Debería funcionar idénticamente en ambos casos.It should operate identically in both cases.

Si se crean instancias del ámbito con RequiresNew, siempre es el ámbito de la raíz.If the scope is instantiated with RequiresNew, it is always the root scope. Inicia una nueva transacción y su transacción se vuelve la nueva transacción ambiente dentro del ámbito.It starts a new transaction, and its transaction becomes the new ambient transaction inside the scope.

Si se crea del ámbito instancias con Suppress, nunca toma la parte en una transacción, sin tener en cuenta si una transacción ambiente está presente.If the scope is instantiated with Suppress, it never takes part in a transaction, regardless of whether an ambient transaction is present. Tiene un ámbito que se crea una instancia con este valor siempre null como su transacción ambiente.A scope instantiated with this value always have null as its ambient transaction.

Las opciones anteriores se resumen en la tabla siguiente.The above options are summarized in the following table.

TransactionScopeOptionTransactionScopeOption Transacción ambienteAmbient Transaction El ámbito toma parte.The scope takes part in
ObligatorioRequired NoNo Nueva transacción (será la raíz)New Transaction (will be the root)
Se requiere nuevaRequires New NoNo Nueva transacción (será la raíz)New Transaction (will be the root)
SuprimirSuppress NoNo Sin transacciónNo Transaction
ObligatorioRequired Yes Transacción ambienteAmbient Transaction
Se requiere nuevaRequires New Yes Nueva transacción (será la raíz)New Transaction (will be the root)
SuprimirSuppress Yes Sin transacciónNo Transaction

Cuando un objeto TransactionScope une una transacción ambiente existente, al eliminar el objeto de ámbito, no se puede finalizar la transacción, a menos que el ámbito anule la transacción.When a TransactionScope object joins an existing ambient transaction, disposing of the scope object may not end the transaction, unless the scope aborts the transaction. Si un ámbito de la raíz creara la transacción ambiente, solo cuando el ámbito de la raíz se elimina, se llama Commit en la transacción.If the ambient transaction was created by a root scope, only when the root scope is disposed of, does Commit get called on the transaction. Si se crea la transacción manualmente, la transacción finaliza cuando se anula o cuando su creador la confirma.If the transaction was created manually, the transaction ends when it is either aborted, or committed by its creator.

El ejemplo siguiente muestra un objeto TransactionScope que crea tres objetos de ámbito anidados, cada uno con instancias con un valor TransactionScopeOption diferente.The following example shows a TransactionScope object that creates three nested scope objects, each instantiated with a different TransactionScopeOption value.

using(TransactionScope scope1 = new TransactionScope())   
//Default is Required   
{   
     using(TransactionScope scope2 = new   
      TransactionScope(TransactionScopeOption.Required))   
     {  
     ...  
     }   
  
     using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew))   
     {  
     ...  
     }   
  
     using(TransactionScope scope4 = new   
        TransactionScope(TransactionScopeOption.Suppress))   
    {  
     ...  
    }   
}  

El ejemplo muestra un bloque de código sin cualquier transacción ambiente que crea un nuevo ámbito (scope1) con Required.The example shows a code block without any ambient transaction creating a new scope (scope1) with Required. El ámbito scope1 es un ámbito raíz porque cuando crea una nueva transacción (la transacción A) y hace que la transacción A sea transacción ambiente.The scope scope1 is a root scope as it creates a new transaction (Transaction A) and makes Transaction A the ambient transaction. Scope1 a continuación, crea tres objetos más, cada uno con otro TransactionScopeOption valor.Scope1 then creates three more objects, each with a different TransactionScopeOption value. Por ejemplo, scope2 se crea con Requiredy hay subsecuentemente una transacción ambiente, que se une la primera transacción creada por scope1.For example, scope2 is created with Required, and since there is an ambient transaction, it joins the first transaction created by scope1. Observe que scope3 es el ámbito de la raíz de una nueva transacción, y scope4 no tiene ninguna transacción ambiente.Note that scope3 is the root scope of a new transaction, and that scope4 has no ambient transaction.

Aunque el valor predeterminado y más comúnmente utilizado de TransactionScopeOption es Required, cada uno de los otros valores tiene su propósito único.Although the default and most commonly used value of TransactionScopeOption is Required, each of the other values has its unique purpose.

Código no transaccional dentro de un ámbito de transacciónNon-transactional code inside a transaction scope

Suppress es útil cuando desea conservar las operaciones realizadas por la sección de código y no desea anular la transacción ambiente si se producen errores en las operaciones.Suppress is useful when you want to preserve the operations performed by the code section, and do not want to abort the ambient transaction if the operations fail. Por ejemplo, al desear realizar un registro u operaciones de la auditoría, o al desear publicar los eventos a los suscriptores sin tener en cuenta si su transacción ambiente se confirma o sufre interrupciones.For example, when you want to perform logging or audit operations, or when you want to publish events to subscribers regardless of whether your ambient transaction commits or aborts. Este valor le permite tener una sección de código no transaccional dentro de un ámbito de la transacción, como se muestra en el ejemplo siguiente.This value allows you to have a non-transactional code section inside a transaction scope, as shown in the following example.

using(TransactionScope scope1 = new TransactionScope())  
{  
     try  
     {  
          //Start of non-transactional section   
          using(TransactionScope scope2 = new  
             TransactionScope(TransactionScopeOption.Suppress))  
          {  
               //Do non-transactional work here  
          }  
          //Restores ambient transaction here  
   }  
     catch  
     {}  
   //Rest of scope1  
}  

Votar dentro de un ámbito anidadoVoting inside a nested scope

Aunque un ámbito anidado puede unir la transacción ambiente del ámbito de la raíz, llamar Complete en el ámbito anidado no tiene ningún efecto en el ámbito de la raíz.Although a nested scope can join the ambient transaction of the root scope, calling Complete in the nested scope has no affect on the root scope. Sólo si todos los ámbitos del ámbito de la raíz, hasta el último del ámbito anidado, votan para confirmar la transacción, la transacción se confirmará.Only if all the scopes from the root scope down to the last nested scope vote to commit the transaction, will the transaction be committed. Si no se llama a Complete en un ámbito anidado afectará al ámbito de la raíz ya que la transacción ambiente se anulará inmediatamente.Not calling Complete in a nested scope will affect the root scope as the ambient transaction will immediately be aborted.

Establecer el tiempo de espera de TransactionScopeSetting the TransactionScope timeout

Algunos de los constructores sobrecargados de TransactionScope aceptan un valor de tipo TimeSpan, que se utiliza para controlar el tiempo de espera de la transacción.Some of the overloaded constructors of TransactionScope accept a value of type TimeSpan, which is used to control the timeout of the transaction. Un conjunto de tiempos de espera establecidos a cero significa un tiempo de espera infinito.A timeout set to zero means an infinite timeout. El tiempo de espera infinito es principalmente útil para depurar, al desear aislar un problema en su lógica comercial caminando a través de su código, y no desear la transacción que depura el tiempo de espera mientras intenta buscar el problema.Infinite timeout is useful mostly for debugging, when you want to isolate a problem in your business logic by stepping through your code, and you do not want the transaction you debug to time out while you attempt to locate the problem. Sea sumamente cuidadoso utilizando el valor de tiempo de espera infinito en todos los otros casos, porque invalida las medidas de seguridad contra los interbloqueos de la transacción.Be extremely careful using the infinite timeout value in all other cases, because it overrides the safeguards against transaction deadlocks.

Se establece normalmente el tiempo de espera TransactionScope en los valores distintos del valor predeterminado en dos casos.You typically set the TransactionScope timeout to values other than default in two cases. El primero durante el desarrollo, al desear probar la manera en que su aplicación administra las transacciones anuladas.The first is during development, when you want to test the way your application handles aborted transactions. Estableciendo el tiempo de espera en un valor pequeño (como un milisegundo), hace que su transacción produzca un error y observa así su código de control de errores.By setting the timeout to a small value (such as one millisecond), you cause your transaction to fail and can thus observe your error handling code. El segundo caso en el que establece el valor para ser menor que el tiempo de espera predeterminado es al creer que el ámbito está implicado en la contención del recurso, produciendo los interbloqueos.The second case in which you set the value to be less than the default timeout is when you believe that the scope is involved in resource contention, resulting in deadlocks. En ese caso, desea anular lo antes posible la transacción y no esperar para que el tiempo de espera predeterminado expire.In that case, you want to abort the transaction as soon as possible and not wait for the default timeout to expire.

Cuando un ámbito combina una transacción ambiente pero especifica un tiempo de espera menor que el de la transacción ambiente, el nuevo tiempo de espera más corto se exige en el objeto TransactionScope y el ámbito debe finalizar dentro de la hora anidada especificada o se anula la transacción automáticamente.When a scope joins an ambient transaction but specifies a smaller timeout than the one the ambient transaction is set to, the new, shorter timeout is enforced on the TransactionScope object, and the scope must end within the nested time specified, or the transaction is automatically aborted. Si el tiempo de espera del ámbito anidado es más que eso de la transacción ambiente, no tiene ningún efecto.If the nested scope's timeout is more than that of the ambient transaction, it has no effect.

Establecer el nivel de aislamiento de TransactionScopeSetting the TransactionScope isolation level

Algunos de los constructores sobrecargados de TransactionScope aceptan una estructura de tipo TransactionOptions para especificar un nivel de aislamiento, además de un valor de tiempo de espera.Some of the overloaded constructors of TransactionScope accept a structure of type TransactionOptions to specify an isolation level, in addition to a timeout value. De forma predeterminada, la transacción se ejecuta con nivel de aislamiento establecido en Serializable.By default, the transaction executes with isolation level set to Serializable. La selección de un nivel de aislamiento distinto de Serializable se utiliza normalmente para los sistemas de lectura-intensivos.Selecting an isolation level other than Serializable is commonly used for read-intensive systems. Esto requiere un sólido entendimiento de teoría del procesamiento de transacciones y las semántica de la propia transacción, los problemas de simultaneidad implicados y las consecuencias para la coherencia del sistema.This requires a solid understanding of transaction processing theory and the semantics of the transaction itself, the concurrency issues involved, and the consequences for system consistency.

Además, no todos los administradores de recursos admiten todos los niveles de aislamiento y pueden elegir tomar parte en la transacción en un nivel más alto que el que se configuró.In addition, not all resource managers support all levels of isolation, and they may elect to take part in the transaction at a higher level than the one configured.

Cada nivel de aislamiento además de Serializable es susceptible a la inconsistencia que es el resultado de otras transacciones que tienen acceso a la misma información.Every isolation level besides Serializable is susceptible to inconsistency resulting from other transactions accessing the same information. La diferencia entre los niveles de aislamiento diferentes es la manera en que se utilizan los bloqueos de la lectura y escritura.The difference between the different isolation levels is in the way read and write locks are used. Se puede contener un bloqueo solo cuando la transacción tiene acceso a los datos en el administrador de recursos, o se puede contener hasta que la transacción se confirme o anule.A lock can be held only when the transaction accesses the data in the resource manager, or it can be held until the transaction is committed or aborted. Lo primero es mejor para el rendimiento, lo último para la coherencia.The former is better for throughput, the latter for consistency. Los dos tipos de bloqueos y los dos tipos de operaciones (lectura/escritura) proporcionan cuatro niveles de aislamiento básicos.The two kinds of locks and the two kinds of operations (read/write) give four basic isolation levels. Vea IsolationLevel para obtener más información.See IsolationLevel for more information.

Al utilizar los objetos TransactionScope anidados, todos los ámbitos anidados se deben configurar para utilizar exactamente el mismo nivel de aislamiento si desean unir la transacción ambiente.When using nested TransactionScope objects, all nested scopes must be configured to use exactly the same isolation level if they want to join the ambient transaction. Si un objeto TransactionScope anidado intenta unir la transacción ambiente todavía especifica un nivel de aislamiento diferente, se inicia ArgumentException.If a nested TransactionScope object tries to join the ambient transaction yet it specifies a different isolation level, an ArgumentException is thrown.

Interoperabilidad con COM+Interop with COM+

Al crear que una nueva instancia TransactionScope, se puede utilizar la enumeración EnterpriseServicesInteropOption en uno de los constructores para especificar cómo interactuar con COM+.When you create a new TransactionScope instance, you can use the EnterpriseServicesInteropOption enumeration in one of the constructors to specify how to interact with COM+. Para obtener más información, consulte interoperabilidad con Enterprise Services y transacciones de COM +.For more information on this, see Interoperability with Enterprise Services and COM+ Transactions.

Vea tambiénSee also