Implementar a simultaneidade otimista com o SqlDataSource (VB)

por Scott Mitchell

Baixar PDF

Neste tutorial, examinamos o essencial do controle de simultaneidade otimista e, em seguida, exploramos como implementá-lo usando o controle SqlDataSource.

Introdução

No tutorial anterior, examinamos como adicionar recursos de inserção, atualização e exclusão ao controle SqlDataSource. Em suma, para fornecer esses recursos, precisávamos especificar a instrução , ou DELETE SQL correspondente INSERTUPDATEnas propriedades , InsertCommandUpdateCommandou DeleteCommand do controle, juntamente com os parâmetros apropriados nas InsertParameterscoleções , UpdateParameterse DeleteParameters . Embora essas propriedades e coleções possam ser especificadas manualmente, o botão Avançado do Assistente para Configurar Fonte de Dados oferece uma caixa de seleção Gerar INSERTinstruções , UPDATEe DELETE que criará automaticamente essas instruções com base na SELECT instrução .

Junto com a caixa de seleção Gerar INSERTinstruções , UPDATEe DELETE , a caixa de diálogo Opções Avançadas de Geração de SQL inclui uma opção Usar simultaneidade otimista (consulte Figura 1). Quando verificadas, as WHERE cláusulas nas instruções e DELETE geradas automaticamente UPDATE são modificadas para executar apenas a atualização ou a exclusão se os dados de banco de dados subjacentes não tiverem sido modificados desde que o usuário carregou os dados pela última vez na grade.

Você pode adicionar suporte de simultaneidade otimista na caixa de diálogo Opções avançadas de geração de SQL

Figura 1: Você pode adicionar suporte de simultaneidade otimista da caixa de diálogo Opções avançadas de geração de SQL

De volta ao tutorial Implementando simultaneidade otimista , examinamos os conceitos básicos do controle de simultaneidade otimista e como adicioná-lo ao ObjectDataSource. Neste tutorial, vamos retocar o essencial do controle de simultaneidade otimista e, em seguida, explorar como implementá-lo usando o SqlDataSource.

Uma recapitulação da simultaneidade otimista

Para aplicativos Web que permitem que vários usuários simultâneos editem ou excluam os mesmos dados, existe a possibilidade de um usuário substituir acidentalmente outras alterações. No tutorial Implementando simultaneidade otimista , forneci o seguinte exemplo:

Imagine que dois usuários, Jisun e Sam, estavam visitando uma página em um aplicativo que permitia aos visitantes atualizar e excluir produtos por meio de um controle GridView. Ambos clicam no botão Editar para Chai na mesma hora. O Jisun altera o nome do produto para Chai Tea e clica no botão Atualizar. O resultado líquido é uma instrução UPDATE enviada ao banco de dados, que define todos os campos atualizáveis do produto (embora Jisun tenha atualizado apenas um campo, ProductName). Neste momento, o banco de dados tem os valores Chai Tea, a categoria Bebidas, o fornecedor Liquids Exóticos e assim por diante para este produto específico. No entanto, a tela GridView no Sam ainda mostra o nome do produto na linha Editável GridView como Chai. Alguns segundos após as alterações do Jisun terem sido confirmadas, Sam atualiza a categoria para Condimentos e clica em Atualizar. Isso resulta em uma instrução UPDATE enviada ao banco de dados que define o nome do produto como Chai, a CategoryID para a ID da categoria condimentos correspondente e assim por diante. As alterações de Jisun no nome do produto foram substituídas.

A Figura 2 ilustra essa interação.

Quando dois usuários atualizam simultaneamente um registro, há potencial para que as alterações de um usuário substituam os outros s

Figura 2: quando dois usuários atualizam simultaneamente um registro, há potencial para alterações de um usuário para substituir os outros s (clique para exibir a imagem em tamanho real)

Para evitar que esse cenário se desenvolva, uma forma de controle de simultaneidade deve ser implementada. Simultaneidade otimista O foco deste tutorial funciona com a suposição de que, embora possa haver conflitos de simultaneidade de vez em quando, a grande maioria das vezes em que esses conflitos não surgirão. Portanto, se um conflito surgir, o controle de simultaneidade otimista simplesmente informa ao usuário que suas alterações não podem ser salvas porque outro usuário modificou os mesmos dados.

Observação

Para aplicativos em que se supõe-se que haverá muitos conflitos de simultaneidade ou se esses conflitos não forem toleráveis, o controle de simultaneidade pessimista poderá ser usado. Consulte o tutorial Implementando simultaneidade otimista para obter uma discussão mais detalhada sobre o controle de simultaneidade pessimista.

O controle de simultaneidade otimista funciona garantindo que o registro que está sendo atualizado ou excluído tenha os mesmos valores que quando o processo de atualização ou exclusão foi iniciado. Por exemplo, ao clicar no botão Editar em um GridView editável, os valores dos registros são lidos do banco de dados e exibidos em TextBoxes e outros controles da Web. Esses valores originais são salvos pelo GridView. Posteriormente, depois que o usuário fizer suas alterações e clicar no botão Atualizar, a UPDATE instrução usada deverá levar em conta os valores originais mais os novos valores e atualizar apenas o registro de banco de dados subjacente se os valores originais que o usuário começou a editar forem idênticos aos valores ainda no banco de dados. A Figura 3 ilustra essa sequência de eventos.

Para que a atualização ou exclusão seja bem-sucedida, os valores originais devem ser iguais aos valores atuais do banco de dados

Figura 3: para que a atualização ou a exclusão tenham êxito, os valores originais devem ser iguais aos valores atuais do banco de dados (clique para exibir a imagem em tamanho real)

Há várias abordagens para implementar a simultaneidade otimista (consulte a Lógica otimista de atualização de simultaneidade de Peter A. Bromberg para obter uma breve visão de várias opções). A técnica usada pelo SqlDataSource (bem como pelo ADO.NET Conjuntos de Dados Tipados usados em nossa Camada de Acesso a Dados) aumenta a WHERE cláusula para incluir uma comparação de todos os valores originais. A instrução a seguir UPDATE , por exemplo, atualiza o nome e o preço de um produto somente se os valores atuais do banco de dados forem iguais aos valores que foram originalmente recuperados ao atualizar o registro no GridView. Os @ProductName parâmetros e @UnitPrice contêm os novos valores inseridos pelo usuário, enquanto @original_ProductName e @original_UnitPrice contêm os valores que foram originalmente carregados no GridView quando o botão Editar foi clicado:

UPDATE Products SET
    ProductName = @ProductName,
    UnitPrice = @UnitPrice
WHERE
    ProductID = @original_ProductID AND
    ProductName = @original_ProductName AND
    UnitPrice = @original_UnitPrice

Como veremos neste tutorial, habilitar o controle de simultaneidade otimista com o SqlDataSource é tão simples quanto verificar uma caixa de seleção.

Etapa 1: Criando um SqlDataSource que dá suporte à simultaneidade otimista

Comece abrindo a OptimisticConcurrency.aspx página da SqlDataSource pasta. Arraste um controle SqlDataSource da Caixa de Ferramentas para o Designer, definindo sua ID propriedade como ProductsDataSourceWithOptimisticConcurrency. Em seguida, clique no link Configurar Fonte de Dados da marca inteligente do controle. Na primeira tela do assistente, escolha trabalhar com o NORTHWINDConnectionString e clique em Avançar.

Escolha Trabalhar com o NORTHWINDConnectionString

Figura 4: Escolha Trabalhar com o NORTHWINDConnectionString (Clique para exibir a imagem em tamanho real)

Neste exemplo, adicionaremos um GridView que permite aos usuários editar a Products tabela. Portanto, na tela Configurar a Instrução Select, escolha a Products tabela na lista suspensa e selecione as ProductIDcolunas , ProductName, UnitPricee Discontinued , conforme mostrado na Figura 5.

Na tabela Products, retorne as colunas ProductID, ProductName, UnitPrice e Descontinuada

Figura 5: Na Tabela, retorne as ProductsProductIDcolunas , ProductName, UnitPricee Discontinued (Clique para exibir a imagem em tamanho real)

Depois de escolher as colunas, clique no botão Avançado para abrir a caixa de diálogo Opções Avançadas de Geração de SQL. Marque as caixas de seleção Gerar INSERTinstruções , UPDATEe DELETE e Usar simultaneidade otimista e clique em OK (consulte a Figura 1 para obter uma captura de tela). Conclua o assistente clicando em Avançar e em Concluir.

Depois de concluir o assistente Configurar Fonte de Dados, dedique um momento para examinar as propriedades e resultantes DeleteCommand e UpdateCommand as DeleteParameters coleções e UpdateParameters . A maneira mais fácil de fazer isso é clicar na guia Origem no canto inferior esquerdo para ver a sintaxe declarativa da página. Lá, você encontrará um UpdateCommand valor de:

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued

Com sete parâmetros na UpdateParameters coleção:

<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ...>
    <DeleteParameters>
      ...
    </DeleteParameters>
    <UpdateParameters>
        <asp:Parameter Name="ProductName" Type="String" />
        <asp:Parameter Name="UnitPrice" Type="Decimal" />
        <asp:Parameter Name="Discontinued" Type="Boolean" />
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </UpdateParameters>
    ...
</asp:SqlDataSource>

Da mesma forma, a propriedade e DeleteParameters a DeleteCommand coleção devem ser semelhantes às seguintes:

DELETE FROM [Products]
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ...>
    <DeleteParameters>
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </DeleteParameters>
    <UpdateParameters>
        ...
    </UpdateParameters>
    ...
</asp:SqlDataSource>

Além de aumentar as WHERE cláusulas das UpdateCommand propriedades e DeleteCommand (e adicionar os parâmetros adicionais às respectivas coleções de parâmetros), selecionar a opção Usar simultaneidade otimista ajusta duas outras propriedades:

Quando o controle da Web de dados invoca o método ou Delete() sqlDataSourceUpdate(), ele passa os valores originais. Se a propriedade sqlDataSource for ConflictDetection definida como CompareAllValues, esses valores originais serão adicionados ao comando . A OldValuesParameterFormatString propriedade fornece o padrão de nomenclatura usado para esses parâmetros de valor originais. O assistente Configurar Fonte de Dados usa original_{0} e nomeia cada parâmetro original nas UpdateCommand propriedades e DeleteCommand nas UpdateParameters coleções e DeleteParameters adequadamente.

Observação

Como não estamos usando os recursos de inserção do controle SqlDataSource, fique à vontade para remover a InsertCommand propriedade e sua InsertParameters coleção.

ManipulandoNULLcorretamente valores

Infelizmente, as instruções aumentadas UPDATE e DELETE geradas automaticamente pelo assistente Configurar Fonte de Dados ao usar simultaneidade otimista não funcionam com registros que contêm NULL valores. Para ver o motivo, considere nosso SqlDataSource s UpdateCommand:

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued

A UnitPrice coluna na Products tabela pode ter NULL valores. Se um registro específico tiver um NULL valor para UnitPrice, a parte da [UnitPrice] = @original_UnitPriceWHERE cláusula sempre será avaliada como False porque NULL = NULL sempre retornará False. Portanto, os registros que contêm NULL valores não podem ser editados ou excluídos, pois as UPDATE cláusulas WHERE e DELETE instruções não retornarão nenhuma linha para atualizar ou excluir.

Observação

Esse bug foi relatado pela primeira vez à Microsoft em junho de 2004 no SqlDataSource gera instruções SQL incorretas e supostamente está agendado para ser corrigido na próxima versão do ASP.NET.

Para corrigir isso, precisamos atualizar manualmente as WHERE cláusulas nas UpdateCommand propriedades e DeleteCommand para todas as colunas que podem ter NULL valores. Em geral, altere [ColumnName] = @original_ColumnName para:

(
   ([ColumnName] IS NULL AND @original_ColumnName IS NULL)
     OR
   ([ColumnName] = @original_ColumnName)
)

Essa modificação pode ser feita diretamente por meio da marcação declarativa, por meio das opções UpdateQuery ou DeleteQuery do janela Propriedades ou por meio das guias UPDATE e DELETE na opção Especificar uma instrução SQL personalizada ou procedimento armazenado no assistente Configurar Fonte de Dados. Novamente, essa modificação deve ser feita para cada coluna na UpdateCommand cláusula e DeleteCommand s WHERE que podem conter NULL valores.

Aplicar isso ao nosso exemplo resulta nos seguintes valores e DeleteCommand modificadosUpdateCommand:

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
        OR ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued
DELETE FROM [Products]
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
        OR ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued

Etapa 2: Adicionar um GridView com Opções de Edição e Exclusão

Com o SqlDataSource configurado para dar suporte à simultaneidade otimista, tudo o que resta é adicionar um controle da Web de dados à página que utiliza esse controle de simultaneidade. Para este tutorial, vamos adicionar um GridView que fornece a funcionalidade de edição e exclusão. Para fazer isso, arraste um GridView da Caixa de Ferramentas para o Designer e defina como IDProducts. Na marca inteligente GridView, associe-a ProductsDataSourceWithOptimisticConcurrency ao controle SqlDataSource adicionado na Etapa 1. Por fim, marcar as opções Habilitar Edição e Habilitar Exclusão da marca inteligente.

Associar o GridView ao SqlDataSource e habilitar a edição e exclusão

Figura 6: Associar o GridView ao SqlDataSource e Habilitar Edição e Exclusão (Clique para exibir a imagem em tamanho real)

Depois de adicionar o GridView, configure sua aparência removendo o ProductID BoundField, alterando a ProductName propriedade BoundField para HeaderText Product e atualizando o UnitPrice BoundField para que sua HeaderText propriedade seja simplesmente Price. O ideal é aprimorar a interface de edição para incluir um RequiredFieldValidator para o ProductName valor e um CompareValidator para o UnitPrice valor (para garantir que ele seja um valor numérico formatado corretamente). Consulte o tutorial Personalizando a Interface de Modificação de Dados para obter uma visão mais detalhada sobre como personalizar a interface de edição do GridView.

Observação

O estado de exibição do GridView deve ser habilitado, pois os valores originais passados do GridView para o SqlDataSource são armazenados no estado de exibição.

Depois de fazer essas modificações no GridView, a marcação declarativa GridView e SqlDataSource deve ser semelhante à seguinte:

<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ConflictDetection="CompareAllValues"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    DeleteCommand=
        "DELETE FROM [Products]
         WHERE [ProductID] = @original_ProductID
         AND [ProductName] = @original_ProductName
         AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
              OR ([UnitPrice] = @original_UnitPrice))
         AND [Discontinued] = @original_Discontinued"
    OldValuesParameterFormatString=
        "original_{0}"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
         FROM [Products]"
    UpdateCommand=
        "UPDATE [Products]
         SET [ProductName] = @ProductName, [UnitPrice] = @UnitPrice,
            [Discontinued] = @Discontinued
         WHERE [ProductID] = @original_ProductID
         AND [ProductName] = @original_ProductName
         AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
            OR ([UnitPrice] = @original_UnitPrice))
        AND [Discontinued] = @original_Discontinued">
    <DeleteParameters>
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </DeleteParameters>
    <UpdateParameters>
        <asp:Parameter Name="ProductName" Type="String" />
        <asp:Parameter Name="UnitPrice" Type="Decimal" />
        <asp:Parameter Name="Discontinued" Type="Boolean" />
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="Products" runat="server"
    AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="ProductsDataSourceWithOptimisticConcurrency">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>

Para ver o controle de simultaneidade otimista em ação, abra duas janelas do navegador e carregue a OptimisticConcurrency.aspx página em ambas. Clique nos botões Editar para o primeiro produto em ambos os navegadores. Em um navegador, altere o nome do produto e clique em Atualizar. O navegador fará o postback e o GridView retornará ao modo de pré-edição, mostrando o novo nome do produto para o registro recém-editado.

Na segunda janela do navegador, altere o preço (mas deixe o nome do produto como seu valor original) e clique em Atualizar. No postback, a grade retorna ao modo de pré-edição, mas a alteração no preço não é registrada. O segundo navegador mostra o mesmo valor que o primeiro, o novo nome do produto com o preço antigo. As alterações feitas na segunda janela do navegador foram perdidas. Além disso, as alterações foram perdidas silenciosamente, pois não havia exceção ou mensagem indicando que uma violação de simultaneidade acabou de ocorrer.

As alterações na segunda janela do navegador foram silenciosamente perdidas

Figura 7: As alterações na segunda janela do navegador foram silenciosamente perdidas (clique para exibir a imagem em tamanho real)

O motivo pelo qual as alterações do segundo navegador não foram confirmadas foi porque a UPDATE cláusula da WHERE instrução filtrava todos os registros e, portanto, não afetava nenhuma linha. Vamos examinar a instrução UPDATE novamente:

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL) OR
        ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued

Quando a segunda janela do navegador atualiza o registro, o nome do produto original especificado na WHERE cláusula não corresponde ao nome do produto existente (já que ele foi alterado pelo primeiro navegador). Portanto, a instrução [ProductName] = @original_ProductName retorna False e o UPDATE não afeta nenhum registro.

Observação

Excluir funciona da mesma maneira. Com duas janelas do navegador abertas, comece editando um determinado produto com um e salvando suas alterações. Depois de salvar as alterações em um navegador, clique no botão Excluir para o mesmo produto no outro. Como os valores originais não correspondem à DELETE cláusula da WHERE instrução , a exclusão falha silenciosamente.

Da perspectiva do usuário final na segunda janela do navegador, depois de clicar no botão Atualizar, a grade retorna ao modo de pré-edição, mas suas alterações foram perdidas. No entanto, não há comentários visuais de que suas alterações não se mantiveram. O ideal é que, se as alterações de um usuário forem perdidas em uma violação de simultaneidade, notificaremos e, talvez, manteremos a grade no modo de edição. Vamos ver como fazer isso.

Etapa 3: Determinar quando ocorreu uma violação de simultaneidade

Como uma violação de simultaneidade rejeita as alterações feitas, seria bom alertar o usuário quando ocorreu uma violação de simultaneidade. Para alertar o usuário, vamos adicionar um controle Web Rótulo à parte superior da página chamada ConcurrencyViolationMessage cuja Text propriedade exibe a seguinte mensagem: Você tentou atualizar ou excluir um registro que foi atualizado simultaneamente por outro usuário. Examine as alterações do outro usuário e, em seguida, refaça sua atualização ou exclusão. Defina a propriedade do CssClass controle Label como Warning, que é uma classe CSS definida em Styles.css que exibe o texto em uma fonte vermelha, itálica, em negrito e grande. Por fim, defina as propriedades e EnableViewState rótulos Visible como False. Isso ocultará o Rótulo, exceto apenas para os postbacks em que definimos explicitamente sua Visible propriedade como True.

Adicionar um controle de rótulo à página para exibir o aviso

Figura 8: Adicionar um controle de rótulo à página para exibir o aviso (clique para exibir a imagem em tamanho real)

Ao executar uma atualização ou exclusão, os manipuladores de RowUpdated eventos e RowDeleted GridView são acionados depois que seu controle de fonte de dados executa a atualização ou exclusão solicitada. Podemos determinar quantas linhas foram afetadas pela operação desses manipuladores de eventos. Se zero linhas foram afetadas, queremos exibir o ConcurrencyViolationMessage Rótulo.

Crie um manipulador de eventos para os RowUpdated eventos e RowDeleted e adicione o seguinte código:

Protected Sub Products_RowUpdated(sender As Object, e As GridViewUpdatedEventArgs) _
    Handles Products.RowUpdated
    If e.AffectedRows = 0 Then
        ConcurrencyViolationMessage.Visible = True
        e.KeepInEditMode = True
        ' Rebind the data to the GridView to show the latest changes
        Products.DataBind()
    End If
End Sub
Protected Sub Products_RowDeleted(sender As Object, e As GridViewDeletedEventArgs) _
    Handles Products.RowDeleted
    If e.AffectedRows = 0 Then
        ConcurrencyViolationMessage.Visible = True
    End If
End Sub

Em ambos os manipuladores de eventos, marcar a e.AffectedRows propriedade e, se for igual a 0, defina a ConcurrencyViolationMessage propriedade Label s Visible como True. No manipulador de RowUpdated eventos, também instruimos o GridView a permanecer no modo de edição definindo a KeepInEditMode propriedade como true. Ao fazer isso, precisamos reassociar os dados à grade para que os dados do outro usuário sejam carregados na interface de edição. Isso é feito chamando o método GridView.DataBind()

Como mostra a Figura 9, com esses dois manipuladores de eventos, uma mensagem muito perceptível é exibida sempre que ocorre uma violação de simultaneidade.

Uma mensagem é exibida na face de uma violação de simultaneidade

Figura 9: Uma mensagem é exibida na face de uma violação de simultaneidade (clique para exibir a imagem em tamanho real)

Resumo

Ao criar um aplicativo Web em que vários usuários simultâneos podem estar editando os mesmos dados, é importante considerar as opções de controle de simultaneidade. Por padrão, os controles da Web de dados ASP.NET e controles de fonte de dados não empregam nenhum controle de simultaneidade. Como vimos neste tutorial, implementar o controle de simultaneidade otimista com o SqlDataSource é relativamente rápido e fácil. O SqlDataSource manipula a maior parte do trabalho para adicionar cláusulas aumentadas WHERE às instruções e DELETE geradas automaticamenteUPDATE, mas há algumas sutilezas na manipulação NULL de colunas de valor, conforme discutido na seção Manipulando NULL valores corretamente.

Este tutorial conclui nosso exame do SqlDataSource. Nossos tutoriais restantes voltarão a trabalhar com dados usando o ObjectDataSource e a arquitetura em camadas.

Programação feliz!

Sobre o autor

Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.