Partager via


Gestion des problèmes d'accès concurrentiel aux bases de données dans les codes de mise à jour (SQLXML 4.0)

S’applique à : SQL ServerAzure SQL Database

Comme d'autres mécanismes de mise à jour de base de données, les codes de mise à jour doivent faire face à des mises à jour simultanées de données dans un environnement multi-utilisateur. Les codes de mise à jour utilisent le contrôle d'accès concurrentiel optimiste, qui utilise la comparaison des données de champ sélectionnées comme instantanés pour garantir que les données à mettre à jour n'ont pas été altérées par une autre application utilisateur depuis qu'elles ont été lues à partir de la base de données. Les codes de mise à jour incluent ces valeurs d’instantané dans le <bloc avant> les codes de mise à jour. Avant de mettre à jour la base de données, le code de mise à jour vérifie les valeurs spécifiées dans le <bloc avant> par rapport aux valeurs actuellement dans la base de données pour vous assurer que la mise à jour est valide.

Le contrôle d'accès concurrentiel optimiste offre trois niveaux de protection dans un code de mise à jour : bas (aucune), intermédiaire et haut. Vous pouvez décider de quel niveau de protection vous avez besoin en spécifiant le code de mise à jour en conséquence.

Niveau de protection le plus bas

Ce niveau correspond à une mise à jour aveugle, dans laquelle la mise à jour est traitée sans se référer aux autres mises à jour effectuées depuis la dernière lecture de la base de données. Dans ce cas, vous spécifiez uniquement la ou les colonnes de clé primaire dans le bloc avant> pour identifier l’enregistrement, et vous spécifiez les informations mises à jour dans le< bloc après>.<

Par exemple, le nouveau numéro de téléphone du contact dans le code de mise à jour suivant est correct, indépendamment de ce que le numéro de téléphone était précédemment. Notez comment le <bloc avant> spécifie uniquement la colonne de clé primaire (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>  

Niveau de protection intermédiaire

Dans ce niveau de protection, le code de mise à jour compare la ou les valeurs actuelles des données qui sont mises à jour avec la ou les valeurs présentes dans la ou les colonnes de la base de données pour garantir que les valeurs n'ont pas été modifiées par quelque autre transaction depuis que l'enregistrement a été lu par votre transaction.

Vous pouvez obtenir ce niveau de protection en spécifiant les colonnes de clé primaire et les colonnes que vous mettez à jour dans le bloc avant>.<

Par exemple, ce code de mise à jour modifie la valeur dans la colonne Phone de la table Person.Contact pour le contact dont ContactID a la valeur 1. Le <bloc avant> spécifie l’attribut Phone pour s’assurer que cette valeur d’attribut correspond à la valeur dans la colonne correspondante de la base de données avant d’appliquer la valeur mise à jour.

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

Niveau de protection élevé

Un niveau de protection élevé garantit qu'un enregistrement reste le même depuis que votre application a lu pour la dernière fois cet enregistrement (autrement dit, depuis que votre application a lu l'enregistrement, celui-ci n'a été modifié par aucune autre transaction).

Il existe deux façons d'obtenir ce niveau de protection élevé contre les mises à jour simultanées :

  • Spécifiez des colonnes supplémentaires dans la table dans le bloc avant>.<

    Si vous spécifiez des colonnes supplémentaires dans le <bloc précédent> , le code de mise à jour compare les valeurs spécifiées pour ces colonnes avec les valeurs qui se trouvaient dans la base de données avant d’appliquer la mise à jour. Si l'une quelconque des colonnes d'enregistrement a changé depuis que votre transaction a lu l'enregistrement, le code de mise à jour n'effectue pas la mise à jour.

    Par exemple, le code de mise à jour suivant met à jour le nom du décalage, mais spécifie des colonnes supplémentaires (StartTime,EndTime) dans le <bloc précédent> , demandant ainsi un niveau de protection plus élevé contre les mises à jour simultanées.

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

    Cet exemple spécifie le niveau de protection le plus élevé en spécifiant toutes les valeurs de colonne de l’enregistrement dans le bloc précédent>.<

  • Spécifiez la colonne timestamp (si disponible) dans le bloc avant>.<

    Au lieu de spécifier toutes les colonnes d’enregistrement dans le bloc précédent>, vous pouvez simplement spécifier la colonne d’horodatage (si la table en a un) ainsi que les colonnes de clé primaire dans le <bloc avant>.< La base de données met à jour la colonne timestamp en spécifiant une valeur unique après chaque mise à jour de l'enregistrement. Dans ce cas, le code de mise à jour compare la valeur de l'horodateur avec la valeur correspondante dans la base de données. La valeur d'horodateur stockée dans la base de données est une valeur binaire. Par conséquent, la colonne timestamp doit être spécifiée dans le schéma sous la forme dt :type="bin.hex », dt :type="bin.base64 », ou sql :datatype="timestamp ».. (Vous pouvez spécifier le type de données xml ou le type de données Microsoft SQL Server.)

Pour tester le code de mise à jour

  1. Créez cette table dans la base de données tempdb :

    USE tempdb  
    CREATE TABLE Customer (  
                 CustomerID  varchar(5),  
                 ContactName varchar(20),  
                 LastUpdated timestamp)  
    
  2. Ajoutez cet exemple d'enregistrement :

    INSERT INTO Customer (CustomerID, ContactName) VALUES   
                         ('C1', 'Andrew Fuller')  
    
  3. Copiez le schéma XSD suivant et collez-le dans le Bloc-notes. Enregistrez-le sous le nom 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. Copiez le code de mise à jour ci-dessous dans le Bloc-notes et enregistrez-le sous le nom ConcurrencySampleTemplate.xml dans le répertoire où vous avez enregistré le schéma créé à l'étape précédente. (Notez que la valeur d'horodateur ci-dessous pour LastUpdated différera dans votre exemple de table Customer et copiez donc la valeur réelle pour LastUpdated à partir de la table et collez-la dans le code de mise à jour.)

    <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. Créez et utilisez le script de test SQLXML 4.0 (Sqlxml4test.vbs) pour exécuter le modèle.

    Pour plus d'informations, voir Utilisation d'ADO pour exécuter des requêtes SQLXML 4.0.

Voici le schéma XDR équivalent :

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

Voir aussi

Considérations de sécurité relatives au code de mise à jour (updategram) (SQLXML 4.0)