Share via


Usando transações com sessões SOAP

Esse recurso será removido em uma versão futura do Microsoft SQL Server. Evite usar esse recurso em desenvolvimentos novos e planeje modificar os aplicativos que atualmente o utilizam.

Uma transação é composta freqüentemente de uma série de lotes enviados um depois do outro e que exigem execução ordenada. Se algum lote na transação não estiver concluído, a transação poderá ser revertida, desfazendo as alterações feitas por lotes anteriores dentro do escopo da transação e restaurando os dados afetados para seu estado anterior.

No acesso a dados SQL tradicionais, a conexão de rede subjacente é considerada para atender a todos os lotes em uma transação com vários lotes conforme é processada e executada. Por exemplo, considere o seguinte como um exemplo da relação entre uma conexão do SQL Server e três transações diferentes:

SQL connection(1)
     --> SQL batch(1)
          --> transaction(1)
     --> SQL batch(2)
          --> transaction(2a)
     --> SQL batch(3)
          --> transaction(2b), transaction(3)

Observe que as transações (1) e (3) são executadas e estão contidas e são confirmadas no mesmo lote; no entanto, a transação (2) se estende em lotes (2) e (3). A conexão subjacente fornece o contexto para verificar se a transação executa todos os lotes na ordem necessária. Com acesso HTTP SOAP, o processamento de transações não pode ser executado assumindo o contexto de uma única conexão de rede subjacente. Dessa forma, para dar suporte ao processamento de transações com vários lotes, uma única sessão SOAP é usada para a mesma finalidade. Por exemplo, o código a seguir mostra como o mesmo padrão de lotes e transações poderá executar sob o acesso HTTP SOAP.

SOAP session(1)
     --> SQL batch(1)
          --> transaction(1)
     --> SQL batch(2)
          --> transaction(2a)
     --> SQL batch(3)
          --> transaction(2b), transaction(3)

Enquanto a mesma sessão SOAP (1) permanece ativa, cada lote pode ser executado em pares separados de solicitação/resposta de SOAP usando-a como o contexto subjacente.

Como transações baseadas em SOAP são gerenciadas pelo SQL Server

As transações SQL são iniciadas na instância do SQL Server quando ocorre uma alteração no estado da transação. Isto pode ser causado por qualquer um dos eventos a seguir que ocorrem por causa do servidor que processa uma solicitação de SOAP a partir de um cliente:

  • Começar Transação

  • Confirmar Transação

  • Reverter Transação

  • Inscrever DTC na transação

  • Remover DTC da transação

Por padrão, o servidor opera em modo de confirmação automática de transação. Este comportamento assume uma relação um-para-um bastante simples de lote para transação e não retorna nenhuma informação da transação (cabeçalhos, descritores) ao cliente.

O modo de confirmação automática da transação poderá ser suficiente para transações (1) e (3) no exemplo anterior. Porém, a transação (2) neste exemplo exigiu mais de um lote e, portanto, exigirá o gerenciamento manual da transação.

Gerenciando transações manualmente

Para gerenciar manualmente a confirmação e a reversão da transação, o cliente SOAP deve definir a opção sqloptions:environmentChangeNotification antes de iniciar a sessão SOAP e, dentro desse cabeçalho, definir o valor de seu atributo transactionBoundary como true, conforme mostrado no seguinte exemplo de mensagem de solicitação de SOAP:

<SOAP-ENV:Envelope  xmlns:SOAP-ENV="https://schemas.xmlsoap.org/soap/envelope/"
              xmlns:sql="https://schemas.microsoft.com/sqlserver/2004/SOAP"
              xmlns:xsi="http://www.w3.org/2004/XMLSchema-instance"
              xmlns:sqlparam="https://schemas.microsoft.com/sqlserver/2004/sqltypes/SqlParameter"
              xmlns:sqlsoaptypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes"
              xmlns:sqloptions="https://schemas.microsoft.com/sqlserver/2004/SOAP/Options">
  <SOAP-ENV:Header>
    <sqloptions:environmentChangeNotifications transactionBoundary="true" />
    <sqloptions:sqlSession initiate="true" timeout="60"/>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <sql:sqlbatch>
      <sql:BatchCommands>
        USE master
        BEGIN TRANSACTION
        CREATE TABLE session_table (col1 int);
      </sql:BatchCommands>
    </sql:sqlbatch>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Isto informa o servidor para desabilitar para o modo de confirmação automática da transação para a sessão atual. Em seguida, o servidor enviará uma resposta de SOAP semelhante a seguinte, em que a sessão é identificada (jGqn3/X73EGHjFxZ12zovw==) e um valor SqlTransaction é retornado e confirma um evento BEGIN TRANSACTION no servidor e um descritor de transação (AQAAADMAAAA=) para o cliente usar em respostas de SOAP subseqüentes que farão parte da mesma transação.

<SOAP-ENV:Envelope xml:space="preserve"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xmlns:SOAP-ENV="https://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:sql="https://schemas.microsoft.com/sqlserver/2004/SOAP"
                   xmlns:sqlsoaptypes="https://schemas.microsoft.com/sqlserver/2004/SOAP/types"
                   xmlns:sqlrowcount="https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlRowCount"                    xmlns:sqlmessage="https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlMessage"                    xmlns:sqlresultstream="https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlResultStream"                    xmlns:sqltransaction="https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlTransaction"                    xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes">
  <SOAP-ENV:Header xmlns:sqloptions="https://schemas.microsoft.com/sqlserver/2004/SOAP/Options">
    <sqloptions:sqlSession sessionId="jGqn3/X73EGHjFxZ12zovw==" timeout="1200">    </sqloptions:sqlSession>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <sql:sqlbatchResponse>
       <sql:sqlbatchResult>
          <sqlresultstream:SqlTransaction xsi:type="sqltransaction:SqlTransaction">
             <sqltransaction:Descriptor>AQAAADMAAAA=</sqltransaction:Descriptor>
             <sqltransaction:Type>Begin</sqltransaction:Type>
          </sqlresultstream:SqlTransaction>
       </sql:sqlbatchResult>
    </sql:sqlbatchResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Depois disso, o cliente será capaz de unir manualmente a transação em solicitações de SOAP subseqüentes, utilizando a mesma identificação de sessão e o mesmo descritor transacional que o servidor retornou na resposta anterior. Isso é mostrado no exemplo a seguir.

<SOAP-ENV:Envelope  xmlns:SOAP-ENV="https://schemas.xmlsoap.org/soap/envelope/"
                    xmlns:sql="https://schemas.microsoft.com/sqlserver/2004/SOAP"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:sqlparam="https://schemas.microsoft.com/sqlserver/2004/sqltypes/SqlParameter"
                    xmlns:sqlsoaptypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes"
                    xmlns:sqloptions="https://schemas.microsoft.com/sqlserver/2004/SOAP/Options">
  <SOAP-ENV:Header>
    <sqloptions:sqlSession sessionId="jGqn3/X73EGHjFxZ12zovw==" transactionDescriptor="AQAAADMAAAA="/>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <sql:sqlbatch>
      <sql:BatchCommands>
        INSERT INTO session_table values (2005)
        COMMIT TRANSACTION
      </sql:BatchCommands>
    </sql:sqlbatch>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Uma solicitação de SOAP poderá unir explicitamente uma transação apenas se o lote estiver sendo executado dentro da mesma sessão SOAP em que a transação foi iniciada. Caso contrário, uma falha de SOAP será retornada se qualquer uma das condições a seguir for verdadeira:

  • Uma identificação de sessão SOAP diferente é especificada.

  • A identificação de sessão SOAP não é especificada.

  • O descritor de transação não é válido para a sessão SOAP atual.

Apenas uma transação de cada vez pode ser usada no atributo transactionDescriptor para cabeçalhos sqlSession. Para criar várias transações independentes na mesma sessão, você pode se inscrever na sessão usando o cabeçalho sqlSession sem especificar o atributo transactionDescriptor. Observe que esta abordagem supõe que o aplicativo cliente esteja acompanhando os diferentes valores de transactionDescriptor. Quando várias transações independentes estão ativas na mesma sessão, não há diferença na associação da transação, apenas especifique o atributo transactionDescriptor no cabeçalho sqlSession em uma solicitação de SOAP.

ObservaçãoObservação

Para determinar o nível de transações aninhadas que são ativas, você pode ler e usar o valor da função Transact-SQL@@TRANCOUNT.

Esquema XSD para sqlTransaction

O seguinte exemplo é o esquema XSD para o cabeçalho sqlTransaction que é usado em mensagens de SOAP:

<xsd:schema
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    attributeFormDefault="qualified"
    elementFormDefault="qualified"
    targetNamespace="https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlTransaction">
<xsd:annotation><xsd:documentation xml:lang="en">&#xd;&#xa;(c) Copyright 2004, Microsoft Corporation&#xd;&#xa;&#xd;&#xa;The following schema for Microsoft SQL Server is presented in XML format and is for informational purposes only. Microsoft Corporation ("Microsoft") may have trademarks, copyrights, or other intellectual property rights covering subject matter in the schema.&#xd;&#xa;&#xd;&#xa;Microsoft does not make any representation or warranty regarding the schema or any product or item developed based on the schema. The schema is provided to you on an AS IS basis.  Microsoft disclaims all express, implied and statutory warranties, including but not limited to the implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement. Without limiting the generality of the foregoing, Microsoft does not make any warranty of any kind that any item developed based on the schema, or any portion of the schema, will not infringe any copyright, patent, trade secret, or other intellectual property right of any person or entity in any country. It is your responsibility to seek licenses for such intellectual property rights where appropriate.&#xd;&#xa;&#xd;&#xa;MICROSOFT SHALL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SCHEMA, INCLUDING WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL (INCLUDING ANY LOST PROFITS), PUNITIVE OR SPECIAL DAMAGES, WHETHER OR NOT MICROSOFT HAS BEEN ADVISED OF SUCH DAMAGES.&#xd;&#xa;</xsd:documentation></xsd:annotation>
  <xsd:complexType name="SqlTransaction">
    <xsd:sequence minOccurs="1" maxOccurs="1">
      <xsd:element name="Descriptor" type="xsd:base64Binary" />
      <xsd:element name="Type">
         <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="Begin"/>
              <xsd:enumeration value="Commit"/>
              <xsd:enumeration value="Rollback"/>
              <xsd:enumeration value="EnlistDTC"/>
              <xsd:enumeration value="Defect"/>
            </xsd:restriction>
         </xsd:simpleType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

O tipo XSI para uma Transação de SQL é xsi:type="typesNs:SqlTransaction", em que typesNs é associado ao namespace https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlTransaction.