Implementar uma transação implícita usando o escopo da transaçãoImplementing an Implicit Transaction using Transaction Scope

O TransactionScope classe fornece uma maneira simples para marcar um bloco de código como participar de uma transação, sem a necessidade de interagir com a própria transação.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. Selecione um escopo de transação e gerenciar a transação ambiente automaticamente.A transaction scope can select and manage the ambient transaction automatically. Devido à sua facilidade de uso e a eficiência, é recomendável que você use o TransactionScope classe ao desenvolver um aplicativo de transação.Due to its ease of use and efficiency, it is recommended that you use the TransactionScope class when developing a transaction application.

Além disso, você não precisa conseguir recursos explicitamente com a transação.In addition, you do not need to enlist resources explicitly with the transaction. Qualquer System.Transactions Gerenciador de recursos (como o SQL Server 2005) pode detectar a existência de uma transação ambiente criada pelo escopo e inscrever-se automaticamente.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.

Criar um escopo de transaçãoCreating a transaction scope

O exemplo a seguir mostra um uso simple do TransactionScope classe.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

O escopo da transação é TransactionScope iniciado assim que você cria um novo objeto.The transaction scope is started once you create a new TransactionScope object. Como ilustrado na amostra de código, recomenda-se que using você crie escopos com uma declaração.As illustrated in the code sample, it is recommended that you create scopes with a using statement. A using declaração está disponível tanto em C# tryquanto no Visual Basic, e funciona como um ... finally bloco para garantir que o escopo seja descartado corretamente.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.

Quando você cria uma instância TransactionScope, o Gerenciador de transações determina qual transação para participar.When you instantiate TransactionScope, the transaction manager determines which transaction to participate in. Uma vez determinado, o escopo sempre participa dessa transação.Once determined, the scope always participates in that transaction. A decisão se baseia em dois fatores: se houver uma transação de ambiente e o valor de TransactionScopeOption parâmetro no construtor.The decision is based on two factors: whether an ambient transaction is present and the value of the TransactionScopeOption parameter in the constructor. A transação ambiente é a transação na qual o código é executado.The ambient transaction is the transaction within which your code executes. Você pode obter uma referência para a transação de ambiente chamando estático Transaction.Current propriedade o Transaction classe.You can obtain a reference to the ambient transaction by calling the static Transaction.Current property of the Transaction class. Para obter mais informações sobre como esse parâmetro é usado, consulte o fluxo de transações gerenciando a seção TransactionScopeOption deste tópico.For more information on how this parameter is used, see the Managing transaction flow using TransactionScopeOption section of this topic.

Concluindo um escopo de transaçãoCompleting a transaction scope

Quando seu aplicativo conclui todo o trabalho que deseja executar em uma transação, você deve chamar o Complete método apenas uma vez para informar o Gerenciador de transações que é aceitável para confirmar a transação.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. É uma prática muito boa Complete colocar a chamada using como a última declaração no bloco.It is very good practice to put the call to Complete as the last statement in the using block.

Deixar de chamar esse método aborta a transação, pois o gerente de transação interpreta isso como uma falha no sistema, ou equivalente a uma exceção lançada no âmbito da transação.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. No entanto, chamar este método não garante que a transação será ser confirmada.However, calling this method does not guarantee that the transaction wil be committed. É simplesmente uma maneira de informar o Gerenciador de transações do seu status.It is merely a way of informing the transaction manager of your status. Depois de chamar o Complete método, você não pode acessar a transação de ambiente usando o Current propriedade e tentar fazer isso resultará em uma exceção é lançada.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.

Se TransactionScope o objeto criou a transação inicialmente, o trabalho real de cometer a transação pelo gerenciador de transações ocorre após a última linha de código no using bloco.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. Se ele não criou a transação, a confirmação ocorre sempre que Commit é chamado pelo proprietário do CommittableTransaction objeto.If it did not create the transaction, the commit occurs whenever Commit is called by the owner of the CommittableTransaction object. Nesse ponto, o gerente de transações liga para os gerentes de Complete recursos e TransactionScope os informa para cometer ou reverter, com base em se o método foi chamado no 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.

A using declaração garante Dispose que TransactionScope o método do objeto seja chamado mesmo se ocorrer uma exceção.The using statement ensures that the Dispose method of the TransactionScope object is called even if an exception occurs. O Dispose método marca o final do escopo da transação.The Dispose method marks the end of the transaction scope. Exceções que ocorrem depois de chamar esse método não podem afetar a transação.Exceptions that occur after calling this method may not affect the transaction. Esse método também restaura a transação de ambiente para ele estado anterior.This method also restores the ambient transaction to it previous state.

Um TransactionAbortedException será lançada se o escopo cria a transação e a transação for anulada.A TransactionAbortedException is thrown if the scope creates the transaction, and the transaction is aborted. Um TransactionInDoubtException será lançada se o Gerenciador de transações não pode chegar a uma decisão de confirmação.A TransactionInDoubtException is thrown if the transaction manager cannot reach a Commit decision. Nenhuma exceção é gerada se a transação for confirmada.No exception is thrown if the transaction is committed.

Revertendo uma transaçãoRolling back a transaction

Se você quiser reverter uma transação, você não deve chamar o Complete método dentro do escopo da transação.If you want to rollback a transaction, you should not call the Complete method within the transaction scope. Por exemplo, você pode lançar uma exceção dentro do escopo.For example, you can throw an exception within the scope. A transação na qual participa também será revertida.The transaction in which it participates in will be rolled back.

Gerenciamento do fluxo de transações usando TransactionScopeOptionManaging transaction flow using TransactionScopeOption

Escopo da transação pode ser aninhado, chamando um método que usa um TransactionScope de dentro de um método que usa seu próprio escopo, como é o caso com o RootMethod método no exemplo a seguir,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();
    }
}

O escopo da transação mais alto é conhecido como o escopo raiz.The top-most transaction scope is referred to as the root scope.

O TransactionScope classe fornece vários construtores sobrecarregados que aceitam uma enumeração do tipo TransactionScopeOption, que define o comportamento transacional do escopo.The TransactionScope class provides several overloaded constructors that accept an enumeration of the type TransactionScopeOption, which defines the transactional behavior of the scope.

Um TransactionScope objeto tem três opções:A TransactionScope object has three options:

  • Una a transação de ambiente ou criar um novo caso não exista.Join the ambient transaction, or create a new one if one does not exist.

  • Ser um novo escopo de raiz, ou seja, iniciar uma nova transação e ter essa transação com a nova transação ambiente dentro de seu próprio escopo.Be a new root scope, that is, start a new transaction and have that transaction be the new ambient transaction inside its own scope.

  • Não fazer parte de uma transação, todo.Not take part in a transaction at all. Como resultado, há uma transação de ambiente.There is no ambient transaction as a result.

Se o escopo é instanciado com Requirede uma transação de ambiente estiver presente, o escopo une a transação.If the scope is instantiated with Required, and an ambient transaction is present, the scope joins that transaction. Se, por outro lado, não há nenhuma transação de ambiente, o escopo cria uma nova transação e se tornar o escopo raiz.If, on the other hand, there is no ambient transaction, then the scope creates a new transaction, and become the root scope. Esse é o valor padrão.This is the default value. Quando Required é usado, o código dentro do escopo não precisa ter um comportamento diferente seja a raiz ou apenas associando a transação de 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. Ele deve operar identicamente em ambos os casos.It should operate identically in both cases.

Se o escopo é instanciado com RequiresNew, é sempre o escopo raiz.If the scope is instantiated with RequiresNew, it is always the root scope. Ele inicia uma nova transação, e sua transação se torna a nova transação ambiente dentro do escopo.It starts a new transaction, and its transaction becomes the new ambient transaction inside the scope.

Se o escopo é instanciado com Suppress, ele nunca faz parte de uma transação, independentemente de se uma transação de 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. Um escopo instanciado com null esse valor sempre tem como transação ambiental.A scope instantiated with this value always have null as its ambient transaction.

As opções acima são resumidas na tabela a seguir.The above options are summarized in the following table.

TransactionScopeOptionTransactionScopeOption Transação de ambienteAmbient Transaction O escopo faz parte doThe scope takes part in
ObrigatórioRequired NãoNo Nova transação (será a raiz)New Transaction (will be the root)
Requer novoRequires New NãoNo Nova transação (será a raiz)New Transaction (will be the root)
SuprimirSuppress NãoNo Nenhuma transaçãoNo Transaction
ObrigatórioRequired SimYes Transação de ambienteAmbient Transaction
Requer novoRequires New SimYes Nova transação (será a raiz)New Transaction (will be the root)
SuprimirSuppress SimYes Nenhuma transaçãoNo Transaction

Quando um TransactionScope objeto ingressa em uma transação ambiente existente, descarte o objeto de escopo não pode terminar a transação, a menos que o escopo anula a transação.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. Se a transação ambiente criada por um escopo de raiz, somente quando o escopo raiz é descartado, não Commit chamado na transação.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. Se a transação foi criada manualmente, a transação termina quando ele é anulado ou confirmado pelo seu criador.If the transaction was created manually, the transaction ends when it is either aborted, or committed by its creator.

A exemplo a seguir mostra um TransactionScope que cria três objetos de escopo aninhado, cada instanciados com outro objeto TransactionScopeOption valor.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))
    {
        //...  
    }
}

O exemplo mostra um bloco de código sem qualquer transação ambiente criando um novo escopo (scope1) com Required.The example shows a code block without any ambient transaction creating a new scope (scope1) with Required. O escopo scope1 é um escopo de raiz quando ele cria uma nova transação (uma transação) e faz com que a transação A transação de ambiente.The scope scope1 is a root scope as it creates a new transaction (Transaction A) and makes Transaction A the ambient transaction. Scope1em seguida, cria mais três TransactionScopeOption objetos, cada um com um valor diferente.Scope1 then creates three more objects, each with a different TransactionScopeOption value. Por exemplo, scope2 é criado com Required, e como há uma transação de ambiente, ele adiciona a primeira transação criada pelo 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 é o escopo da raiz de uma nova transação e que scope4 não tem nenhuma transação de ambiente.Note that scope3 is the root scope of a new transaction, and that scope4 has no ambient transaction.

Embora o padrão e mais comumente usado o valor de TransactionScopeOption é Required, cada um dos outros valores tem sua finalidade exclusiva.Although the default and most commonly used value of TransactionScopeOption is Required, each of the other values has its unique purpose.

Código não transacional dentro de um escopo de transaçãoNon-transactional code inside a transaction scope

Suppressé útil quando você deseja preservar as operações realizadas pela seção de código, e não deseja abortar a transação ambiental se as operações falharem.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 exemplo, quando você deseja executar um log ou operações de auditoria ou quando desejar publicar eventos para assinantes, independentemente de se a transação de ambiente confirma ou anula.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. Esse valor permite que você tenha uma seção de código não-transacional dentro de um escopo de transação, como mostrado no exemplo a seguir.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
}

Votação dentro de um escopo aninhadoVoting inside a nested scope

Embora um escopo aninhado pode unir a transação de ambiente do escopo raiz, chamar Complete no escopo aninhado não tem nenhum efeito sobre o escopo raiz.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. Somente se todos os escopos do escopo raiz até o último escopo aninhado votam para confirmar a transação, a transação será confirmada.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. Não chamar Complete em um escopo aninhado afetará o escopo raiz como a transação ambiente imediatamente será anulada.Not calling Complete in a nested scope will affect the root scope as the ambient transaction will immediately be aborted.

Definir o tempo limite de TransactionScopeSetting the TransactionScope timeout

Alguns dos construtores sobrecarregados de TransactionScope aceitar um valor do tipo TimeSpan, que é usado para controlar o tempo limite da transação.Some of the overloaded constructors of TransactionScope accept a value of type TimeSpan, which is used to control the timeout of the transaction. Um tempo limite definido como zero significa um tempo limite infinito.A timeout set to zero means an infinite timeout. Tempo limite infinito é útil principalmente para depuração, quando quiser isolar um problema em sua lógica de negócios, percorrendo seu código, e você não deseja que a transação que você depurar tempo limite durante a tentativa de localizar o 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. Ser extremamente cauteloso ao usar o valor de tempo limite infinito em todos os outros casos, porque ele substitui as proteções contra bloqueios de transação.Be extremely careful using the infinite timeout value in all other cases, because it overrides the safeguards against transaction deadlocks.

Você normalmente define o TransactionScope tempo limite para valores que não seja padrão nos dois casos.You typically set the TransactionScope timeout to values other than default in two cases. A primeira é durante o desenvolvimento, quando você deseja testar a maneira como o seu aplicativo manipula transações anuladas.The first is during development, when you want to test the way your application handles aborted transactions. Definindo o tempo limite como um valor pequeno (como um milissegundo), você fazer com que a transação falhar e, portanto, pode observar o código de tratamento de erros.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. O segundo caso em que você definir o valor como menor que o tempo limite padrão é quando você acreditar que o escopo está envolvido na contenção de recursos, resultando em bloqueios.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. Nesse caso, você deseja anular a transação assim que possível e aguarda o tempo limite padrão expirar.In that case, you want to abort the transaction as soon as possible and not wait for the default timeout to expire.

Quando um escopo ingressa em uma transação de ambiente, mas Especifica um tempo limite menor do que a transação ambiente é definida como, o tempo limite de novo e mais curto é imposto no TransactionScope objeto e o escopo devem terminar no tempo aninhado especificado ou a transação é cancelada automaticamente.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. Se o tempo limite do escopo aninhado é maior do que a transação de ambiente, ele não tem efeito.If the nested scope's timeout is more than that of the ambient transaction, it has no effect.

Definindo o nível de isolamento de TransactionScopeSetting the TransactionScope isolation level

Alguns dos construtores sobrecarregados de TransactionScope aceitar uma estrutura do tipo TransactionOptions para especificar um nível de isolamento, além de um valor de tempo limite.Some of the overloaded constructors of TransactionScope accept a structure of type TransactionOptions to specify an isolation level, in addition to a timeout value. Por padrão, a transação será executado com nível de isolamento definido como Serializable.By default, the transaction executes with isolation level set to Serializable. Selecionando um nível de isolamento diferente de Serializable é normalmente usado para sistemas com uso intensivo de leitura.Selecting an isolation level other than Serializable is commonly used for read-intensive systems. Isso requer uma compreensão sólida da teoria e a semântica da própria transação, os problemas de simultaneidade envolvidos e as conseqüências de consistência do sistema de processamento de transações.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.

Além disso, nem todos os gerenciadores de recursos oferecer suporte a todos os níveis de isolamento, e eles podem optar por fazer parte de transação em um nível mais alto que o configurado.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 nível de isolamento além Serializable é suscetível a inconsistência resultantes de outras transações que acessam as mesmas informações.Every isolation level besides Serializable is susceptible to inconsistency resulting from other transactions accessing the same information. É a diferença entre os diferentes níveis de isolamento da forma leitura e gravação bloqueios são usados.The difference between the different isolation levels is in the way read and write locks are used. Um bloqueio pode ser mantido somente quando a transação acessa os dados no Gerenciador de recursos, ou pode ser mantida até que a transação é confirmada ou anulada.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. O primeiro é melhor taxa de transferência, o segundo para manter a consistência.The former is better for throughput, the latter for consistency. Os dois tipos de bloqueios e os dois tipos de operações (leitura/gravação) oferecem quatro níveis de isolamento básico.The two kinds of locks and the two kinds of operations (read/write) give four basic isolation levels. Consulte IsolationLevel para obter mais informações.See IsolationLevel for more information.

Quando usando aninhadas TransactionScope objetos, todos os escopos aninhados devem ser configurados para usar exatamente o mesmo nível de isolamento se deseja unir a transação de 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. Se um aninhada TransactionScope objeto tentar unir a transação ambiente ainda Especifica um nível de isolamento diferente, um ArgumentException é lançada.If a nested TransactionScope object tries to join the ambient transaction yet it specifies a different isolation level, an ArgumentException is thrown.

Interoperação com COM+Interop with COM+

Quando você cria um novo TransactionScope instância, você pode usar o EnterpriseServicesInteropOption enumeração em um dos construtores para especificar como interagir com 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 obter mais informações sobre isso, consulte Interoperabilidade com Serviços Corporativos e Transações COM+.For more information on this, see Interoperability with Enterprise Services and COM+ Transactions.

Confira tambémSee also