Condividi tramite


Utilizzo delle transazioni con le sessioni SOAP

Questa caratteristica verrà rimossa a partire da una delle prossime versioni di Microsoft SQL Server. Evitare di utilizzare questa caratteristica in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.

Una transazione è spesso costituita da una serie di batch inviati in sequenza e che richiedono un'esecuzione ordinata. Se un batch nella transazione non è completo, è possibile che venga eseguito il rollback della transazione, annullando le modifiche apportate dai batch precedenti all'interno dell'ambito della transazione e ripristinando i dati interessati allo stato precedente.

Nell'accesso ai dati SQL tradizionale, la connessione di rete sottostante si basa sulla gestione di tutti i batch in una transazione multibatch mentre viene elaborata ed eseguita. Ad esempio, prendere in considerazione quanto segue come esempio della relazione tra una connessione SQL Server e tre diverse transazioni:

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

Si noti che le transazioni (1) e (3) sono eseguite e contenute e ne viene eseguito il commit all'interno dello stesso batch. Tuttavia, la transazione (2) si estende tra i batch (2) e (3). La connessione sottostante offre il contesto necessario ad assicurare che la transazione esegua tutti i batch nell'ordine previsto. Con l'accesso HTTP SOAP, l'elaborazione delle transazioni non può essere eseguita supponendo che il contesto sia una singola connessione di rete sottostante. Pertanto, per supportare l'elaborazione delle transazioni multibatch, una singola sessione SOAP svolge la stessa funzione. Ad esempio, il codice seguente mostra come lo stesso modello di batch e transazioni può venire eseguito con l'accesso HTTP SOAP.

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

Finché la stessa sessione SOAP (1) rimane attiva, ogni batch può essere eseguito in coppie di messaggi di richiesta/risposta SOAP separati utilizzandola come contesto sottostante.

Modalità di gestione delle transazioni basate su SOAP da parte di SQL Server

Le transazioni SQL vengono avviate con l'istanza di SQL Server quando si verifica una modifica dello stato della transazione. Questo può essere determinato da uno degli eventi seguenti che si verificano a causa dell'elaborazione di una richiesta SOAP eseguita da un client a opera del server:

  • Inizio transazione

  • Commit transazione

  • Rollback transazione

  • Integrazione DTC nella transazione

  • Difetto DTC dalla transazione

Per impostazione predefinita, il server opera in modalità autocommit transaction. Questo comportamento presume un rapporto batch-transazione di uno a uno, piuttosto semplice, e non restituisce al client alcuna informazione sulla transazione (intestazioni, descrittori).

La modalità autocommit transaction può essere sufficiente per le transazioni (1) e (3) nell'esempio precedente. Tuttavia, la transazione (2) nell'esempio necessita di più batch e pertanto richiederebbe la gestione manuale della transazione.

Gestione manuale delle transazioni

Per gestire manualmente il commit e il rollback delle transazioni, è necessario che il client SOAP imposti l'opzione sqloptions:environmentChangeNotification prima di inizializzare la sessione SOAP, e che all'interno di tale intestazione imposti il valore del relativo attributo transactionBoundary su true, come illustrato nell'esempio di messaggio di richiesta SOAP seguente:

<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>

Il messaggio indica al server di disattivare la modalità autocommit transaction per la sessione corrente. Il server invierà quindi una risposta SOAP simile a quella seguente, nella quale la sessione viene identificata (jGqn3/X73EGHjFxZ12zovw==) e viene restituito un valore SqlTransaction che conferma un evento BEGIN TRANSACTION sul server e un descrittore di transazione (AQAAADMAAAA=) per il client da utilizzare nelle richieste SOAP successive che saranno parte della stessa transazione.

<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>

Il client sarà quindi in grado di unire in join la transazione nelle richieste SOAP successive utilizzando lo stesso ID sessione e descrittore transazionale restituito dal server nella risposta precedente, come illustrato nell'esempio seguente.

<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>

Una richiesta SOAP può unire in join in modo esplicito una transazione solo se il batch è in esecuzione all'interno della stessa sessione SOAP nella quale è stata avviata la transazione. In caso contrario, viene restituito un errore SOAP se una delle condizioni seguenti è true:

  • Viene specificato un diverso ID sessione SOAP.

  • L'ID sessione SOAP non è specificato.

  • Il descrittore di transazione non è valido per la sessione SOAP corrente.

È possibile utilizzare una sola transazione per volta nell'attributo transactionDescriptor per le intestazioni sqlSession. Per creare più transazioni indipendenti all'interno della stessa sessione, è possibile integrarle nella sessione utilizzando l'intestazione sqlSession senza specificare l'attributo transactionDescriptor. Si noti che questo approccio presuppone che l'applicazione client tenga traccia dei diversi valori di transactionDescriptor. Quando più transazioni indipendenti sono attive all'interno della stessa sessione, non c'è differenza rispetto all'unione in join di una transazione, ma è sufficiente specificare l'attributo transactionDescriptor nell'intestazione sqlSession di una richiesta SOAP.

Nota

Per determinare il livello delle transazioni nidificate attive, è possibile leggere e utilizzare il valore della funzione Transact-SQL@@TRANCOUNT.

Schema XSD per sqlTransaction

Quello seguente è lo schema XSD per l'intestazione sqlTransaction utilizzato nei messaggi 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>

Il tipo XSI per una transazione SQL è xsi:type="typesNs:SqlTransaction", dove typesNs è associato allo spazio dei nomi https://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlTransaction.