Compartilhar via


Manipulando problemas de simultaneidade de banco de dados nos diagramas de atualização (SQLXML 4.0)

Da mesma forma que outros mecanismos de atualização de banco de dados, os diagramas de atualização devem lidar com atualizações simultâneas dos dados em um ambiente multiusuário. Os diagramas de atualização usam o Controle de simultaneidade otimista, que usa a comparação de dados de campos 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 estes valores de instantâneo em seus blocos <before>. Antes de atualizar o banco de dados, o diagrama de atualização verifica os valores que são especificados no bloco <before> e os compara com os valores que estão atualmente no banco de dados para garantir que a atualização é válida.

O Controle de simultaneidade otimista oferece três níveis de proteção em um diagrama de atualização: baixo (nenhum), intermediário e alto. Você pode decidir qual o nível de proteção necessário especificando o diagrama de atualização de acordo com ele.

Nível de proteção mais baixo

Este nível é uma atualização cega, no qual a atualização é processada sem referência a outras atualizações que foram feitas desde que o banco de dados foi lido pela última vez. Nesse caso, você especifica somente a(s) coluna(s) da chave primária no bloco <before> para identificar o registro e as informações atualizadas no bloco <after>.

Por exemplo, o novo número de telefone de contato no seguinte diagrama de atualização está correto, não importando qual tenha sido o número de telefone anteriormente. Observe como o bloco <before> especifica somente a coluna da 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 de proteção intermediário

Neste nível de proteção, o diagrama de atualização 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 foram alterados por alguma outra transação desde que o registro foi lido pela sua transação.

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

Por exemplo, este diagrama de atualização altera o valor na coluna Phone da tabela Person.Contact para o contato com ContactID igual a 1. O bloco <before> especifica o atributo Phone para garantir que este valor de atributo esteja de acordo com o 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>

Nível de proteção alto

Um nível de proteção alto garante que o registro permanecerá o mesmo desde que o seu aplicativo o leu pela última vez (ou seja, desde que o seu aplicativo leu o registro, ele não foi alterado por nenhuma outra transação).

Há duas formas através das quais você pode obter esse nível de proteção alto contra atualizações simultâneas:

  • Especificar colunas adicionais na tabela, no bloco <before>.

    Se você especificar colunas adicionais no bloco <before>, o diagrama de atualização compara os valores que são especificados para estas colunas com aqueles que estavam no banco de dados antes de aplicar a atualização. Se qualquer uma das colunas do registro tiver sido alterada desde que a sua transação leu o registro, o diagrama de atualização não realizará a atualização.

    Por exemplo, o seguinte diagrama de atualização atualiza o nome do turno (Shift), mas especifica colunas adicionais (StartTime,EndTime) no bloco <before>, solicitando, por meio disso, um nível de proteção mais alto 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 <before>.

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

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

Para testar o diagrama de atualização

  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 seguinte esquema XSD e cole-o no Bloco de Notas. Salve 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 seguinte código de diagrama de atualização no Bloco de Notas e salve como ConcurrencySampleTemplate.xml, no mesmo diretório em que você salvou o esquema criado na etapa anterior. (Observe que o seguinte valor de carimbo de data e hora para LastUpdated será diferente na sua tabela Customer de exemplo, portanto copie o valor real de LastUpdated da tabela e cole-o no diagrama de atualização.)

    <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 Usando o ADO para executar consultas do SQLXML 4.0.

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