Compartilhar via


Lidando com problemas de simultaneidade em banco de dados em updategrams (SQLXML 4.0)

Assim como outros mecanismos de atualização de banco de dados, os updategramas devem lidar com atualizações simultâneas de dados em um ambiente multiusuário. Os updategramas usam o Controle de Simultaneidade Otimista, que usa a comparação de dados de campo selecionados como instantâneos para garantir que os dados a serem atualizados não foram alterados por outro aplicativo de usuário desde que foram lidos do banco de dados. Os diagramas de atualização incluem esses valores de instantâneo no <bloco anterior> dos updategramas. Antes de atualizar o banco de dados, o updategram verifica os valores especificados no <bloco anterior> em relação aos valores atualmente no banco de dados para garantir que a atualização seja válida.

O Controle de Simultaneidade Otimista oferece três níveis de proteção em um updategrama: baixo (nenhum), intermediário e alto. Você pode decidir qual nível de proteção você precisa especificando o updategram adequadamente.

Nível mais baixo de proteção

Esse nível é uma atualização cega, na qual a atualização é processada sem referência a outras atualizações que foram feitas desde a última leitura do banco de dados. Nesse caso, você especifica apenas as colunas de chave primária no <bloco anterior> para identificar o registro e especifica as informações atualizadas no <bloco após> .

Por exemplo, o novo número de telefone de contato no programa de atualização a seguir está correto, independentemente do número de telefone anteriormente. Observe como o <bloco anterior> especifica apenas a coluna de chave primária (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>  

Nível intermediário de proteção

Nesse nível de proteção, o updategrama compara os valores atuais dos dados que estão sendo atualizados com os valores nas colunas do banco de dados para garantir que os valores não tenham sido alterados por alguma outra transação desde que o registro foi lido pela transação.

Você pode obter esse nível de proteção especificando as colunas de chave primária e as colunas que você está atualizando no <bloco anterior> .

Por exemplo, este updategram altera o valor na coluna Telefone da tabela Person.Contact para o contato com ContactID de 1. O <bloco anterior> especifica o atributo Phone para garantir que esse valor de atributo corresponda ao valor na coluna correspondente no banco de dados antes de aplicar o valor atualizado.

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

Alto nível de proteção

Um alto nível de proteção garante que o registro permaneça o mesmo desde a última leitura do registro pelo aplicativo (ou seja, como seu aplicativo leu o registro, ele não foi alterado por nenhuma outra transação).

Há duas maneiras de obter esse alto nível de proteção contra atualizações simultâneas:

  • Especifique colunas adicionais na tabela no <bloco anterior> .

    Se você especificar colunas adicionais no <bloco anterior> , o updategrama comparará os valores especificados para essas colunas com os valores que estavam no banco de dados antes de aplicar a atualização. Se qualquer uma das colunas de registro tiver sido alterada desde que a transação leu o registro, o updategrama não executará a atualização.

    Por exemplo, o updategram a seguir atualiza o nome da mudança, mas especifica colunas adicionais (StartTime, EndTime) no <bloco anterior> , solicitando assim um nível mais alto de proteção contra atualizações simultâneas.

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

    Este exemplo especifica o nível mais alto de proteção especificando todos os valores de coluna para o registro no <bloco anterior> .

  • Especifique a coluna de carimbo de data/hora (se disponível) no <bloco anterior> .

    Em vez de especificar todas as colunas de registro no <before> bloco, você pode apenas especificar a coluna de carimbo de data/hora (se a tabela tiver uma) juntamente com as colunas de chave primária no <bloco anterior> . O banco de dados atualiza a coluna de carimbo de data/hora para um valor exclusivo após cada atualização do registro. Nesse caso, o updategram compara o valor do carimbo de data/hora com o valor correspondente no banco de dados. O valor do carimbo de data/hora armazenado no banco de dados é um valor binário. Portanto, a coluna de carimbo de data/hora deve ser especificada no esquema como dt:type="bin.hex", dt:type="bin.base64"ou sql:datatype="timestamp". (Você pode especificar o xml tipo de dados ou o tipo de dados do Microsoft SQL Server.)

Para testar o updategram

  1. Crie esta tabela no banco de dados tempdb :

    USE tempdb  
    CREATE TABLE Customer (  
                 CustomerID  varchar(5),  
                 ContactName varchar(20),  
                 LastUpdated timestamp)  
    
  2. Adicione este registro de exemplo:

    INSERT INTO Customer (CustomerID, ContactName) VALUES   
                         ('C1', 'Andrew Fuller')  
    
  3. Copie o esquema XSD a seguir e cole-o no Bloco de Notas. Salve-o como 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. Copie o código do diagrama de atualização a seguir no Bloco de Notas e salve-o como ConcurrencySampleTemplate.xml no mesmo diretório em que você salvou o esquema criado na etapa anterior. (Observe que o valor do carimbo de data/hora abaixo para LastUpdated será diferente em sua tabela de exemplo cliente, portanto, copie o valor real para LastUpdated da tabela e cole-o no 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. Crie e use o script de teste SQLXML 4.0 (Sqlxml4test.vbs) para executar o modelo.

    Para obter mais informações, consulte Usar o ADO para executar consultas SQLXML 4.0.

Esse é o esquema 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>  

Consulte Também

Considerações sobre segurança do updategram (SQLXML 4.0)