Condividi tramite


Gestione dei problemi di concorrenza di database negli updategram (SQLXML 4.0)

Analogamente ad altri meccanismi di aggiornamento del database, gli updategram devono gestire aggiornamenti simultanei ai dati in un ambiente multiutente. Gli updategram utilizzano il controllo della concorrenza ottimistica, che esegue il confronto dei dati di campo come snapshot per garantire che i dati da aggiornare non siano già stati modificati da un'altra applicazione utente dal momento in cui sono stati letti dal database. Gli updategram includono questi valori di snapshot nel blocco <before> degli updategram. Prima di aggiornare il database, l'updategram controlla i valori specificati attualmente nel blocco <before> rispetto ai valori presenti nel database per verificare la validità dell'aggiornamento.

Il controllo della concorrenza ottimistica offre tre livelli di protezione in un updategram: basso (nessuno), intermedio ed elevato. È possibile stabilire il livello di protezione necessario specificando l'updategram di conseguenza.

Livello di protezione più basso

Questo livello corrisponde a un aggiornamento nascosto, in cui l'aggiornamento viene elaborato senza riferimento ad altri aggiornamenti eseguiti dall'ultima lettura del database. In tal caso, è necessario specificare solo le colonne di chiave primaria nel blocco <before> per identificare il record e specificare le informazioni aggiornate nel blocco <after>.

Il nuovo numero di telefono del contatto nell'updategram seguente, ad esempio, è corretto, indipendentemente dal numero di telefono precedente. Si noti il modo in cui il blocco <before> specifica solo la colonna di chiave primaria (ContactID).

<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
<updg:sync >
<updg:before>
   <Person.Contact ContactID="1" />
</updg:before>
<updg:after>
   <Person.Contact ContactID="1" Phone="111-111-1111" />
</updg:after>
</updg:sync>
</ROOT>

Livello di protezione intermedio

In questo livello di protezione l'updategram confronta i valori correnti dei dati aggiornati con i valori nelle colonne del database per verificare che i valori non siano stati modificati da altre transazioni dalla lettura del record da parte della transazione.

È possibile ottenere questo livello di protezione specificando le colonne di chiave primaria e le colonne aggiornate nel blocco <before>.

Questo updategram, ad esempio, modifica il valore nella colonna Phone della tabella Person.Contact per il contatto con ContactID 1. Il blocco <before> specifica l'attributo Phone per verificare che tale attributo corrisponda al valore presente nella colonna corrispondente del database prima di applicare il valore aggiornato.

<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
<updg:sync >
<updg:before>
   <Person.Contact ContactID="1" Phone="398-555-0132" />
</updg:before>
<updg:after>
   <Person.Contact ContactID="1" Phone="111-111-1111" />
</updg:after>
</updg:sync>
</ROOT>

Livello di protezione elevato

Un livello di protezione elevato garantisce che il record resti inalterato dall'ultima lettura da parte dell'applicazione, ovvero dal momento in cui l'applicazione ha letto il record, che non è stato modificato da alcuna transazione.

Per ottenere questo livello di protezione elevato contro aggiornamenti simultanei, sono disponibili due metodi:

  • Specificare colonne aggiuntive nella tabella nel blocco <before>.

    Se si specificano colonne aggiuntive nel blocco <before>, l'updategram confronta i valori specificati per queste colonne con i valori presenti nel database prima di applicare l'aggiornamento. Se una o più delle colonne dei record è stata modificata dal momento in cui la transazione ha letto il record, l'updategram non esegue l'aggiornamento.

    Nell'updategram seguente, ad esempio, viene aggiornato il nome del turno, ma vengono specificate colonne aggiuntive (StartTime, EndTime) nel blocco <before>, per cui è necessario un livello di protezione maggiore dagli aggiornamenti simultanei.

    <ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
    <updg:sync >
    <updg:before>
       <HumanResources.Shift ShiftID="1" 
                 Name="Day" 
                 StartTime="1900-01-01 07:00:00.000" 
                 EndTime="1900-01-01 15:00:00.000" />
    </updg:before>
    <updg:after>
       <HumanResources.Shift Name="Morning" />
    </updg:after>
    </updg:sync>
    </ROOT>
    

    In questo esempio viene impostato il livello di protezione più elevato specificando tutti i valori di colonna per il record nel blocco <before>.

  • Specificare la colonna timestamp, se disponibile, nel blocco <before>.

    Anziché specificare tutte le colonne dei record nel blocco <before>, è possibile specificare solo la colonna timestamp, se inclusa nella tabella, insieme alle colonne di chiave primaria nel blocco <before>. Il database aggiorna la colonna timestamp a un valore univoco dopo ogni aggiornamento del record. In questo caso, l'updategram confronta il valore del timestamp con il valore corrispondente nel database. Il valore del timestamp archiviato nel database è un valore binary. La colonna timestamp, pertanto, deve essere specificata nello schema come dt:type="bin.hex", dt:type="bin.base64" o sql:datatype="timestamp". È possibile specificare il tipo di dati xml o il tipo di dati di MicrosoftSQL Server.

Per testare l'updategram

  1. Creare la tabella seguente nel database tempdb:

    USE tempdb
    CREATE TABLE Customer (
                 CustomerID  varchar(5),
                 ContactName varchar(20),
                 LastUpdated timestamp)
    
  2. Aggiungere il record di esempio seguente:

    INSERT INTO Customer (CustomerID, ContactName) VALUES 
                         ('C1', 'Andrew Fuller')
    
  3. Copiare lo schema XSD seguente e incollarlo in Blocco note. Salvarlo come file ConcurrencySampleSchema.xml:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:sql="urn:schemas-microsoft-com:mapping-schema">
      <xsd:element name="Customer" sql:relation="Customer" >
       <xsd:complexType>
            <xsd:attribute name="CustomerID"  
                           sql:field="CustomerID" 
                           type="xsd:string" /> 
    
            <xsd:attribute name="ContactName"  
                           sql:field="ContactName" 
                           type="xsd:string" />
    
            <xsd:attribute name="LastUpdated" 
                           sql:field="LastUpdated" 
                           type="xsd:hexBinary" 
                 sql:datatype="timestamp" />
    
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
    
  4. Copiare il codice dell'updategram seguente in Blocco note e salvarlo come ConcurrencySampleTemplate.xml nella stessa directory in cui è stato salvato lo schema creato nel passaggio precedente. Si noti che il valore del timestamp indicato di seguito per LastUpdated differirà nella tabella Customer di esempio. Copiare pertanto il valore effettivo di LastUpdated dalla tabella e incollarlo nell'updategram.

    <ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
    <updg:sync mapping-schema="SampleSchema.xml" >
    <updg:before>
       <Customer CustomerID="C1" 
                 LastUpdated = "0x00000000000007D1" />
    </updg:before>
    <updg:after>
       <Customer ContactName="Robert King" />
    </updg:after>
    </updg:sync>
    </ROOT>
    
  5. Creare e utilizzare lo script di test SQLXML 4.0 (Sqlxml4test.vbs) per eseguire il modello.

    Per ulteriori informazioni, vedere Utilizzo di ADO per eseguire query SQLXML 4.0.

Di seguito viene riportato lo schema XDR equivalente:

<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data"
        xmlns:dt="urn:schemas-microsoft-com:datatypes"
        xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<ElementType name="Customer" sql:relation="Customer" >
    <AttributeType name="CustomerID" />
    <AttributeType name="ContactName" />
    <AttributeType name="LastUpdated"  dt:type="bin.hex" 
                                       sql:datatype="timestamp" />
    <attribute type="CustomerID" />
    <attribute type="ContactName" />
    <attribute type="LastUpdated" />
</ElementType>
</Schema>