Compartilhar via


Instruções passo a passo: identificando uma exceção de simultaneidade

 

Publicado: abril de 2016

Exceções de simultaneidade (DBConcurrencyException) são geradas quando dois usuários tentam alterar os mesmos dados em um banco de dados ao mesmo tempo. Neste passo a passo, você cria um aplicativo do Windows que ilustra a captura um DBConcurrencyException, localizando a linha que causou o erro, e uma estratégia para você pode usar para manipulá-lo.

Este passo a passo leva você através do seguinte processo:

  1. Criar um novo Windows Application projeto.

  2. Criar um novo conjunto de dados com base em Northwind Customers tabela.

  3. Criar um formulário com um DataGridView para exibir os dados.

  4. Preencher um dataset com dados a partir de Customers tabela no banco de dados Northwind.

  5. Após preencher o conjunto de dados, use o Visual Database Tools no Visual Studio para acessar diretamente o Customers tabela de dados e alterar um registro.

  6. Em seguida, no formulário, altere o mesmo registro com um valor diferente, atualizar o conjunto de dados e tentar gravar as alterações no banco de dados, o que resulta em um erro de simultaneidade que está sendo gerado.

  7. Capturar o erro e, em seguida, exiba as diferentes versões do registro, permitindo que o usuário determinar se deseja continuar e atualizar o banco de dados ou para cancelar a atualização.

Pré-requisitos

Para concluir este passo a passo, você precisa:

Dica

Caixas de diálogo e comandos de menu que você vê podem diferir daqueles descritos na Ajuda, dependendo de suas configurações ativas ou edição. Para alterar suas configurações, escolha Import and Export Settings sobre o ferramentas menu. Para obter mais informações, consulte Personalizando configurações de desenvolvimento no Visual Studio.

Criar um novo projeto

Iniciar a passo a passo, criando um novo aplicativo do Windows.

Para criar um novo projeto de aplicativo do Windows

  1. Do arquivo menu, crie um novo projeto.

  2. Selecione uma linguagem de programação a tipos de projeto painel.

  3. Selecione Windows Application no modelos painel.

  4. Nomeie o projeto ConcurrencyWalkthrough, e, em seguida, clique em OK.

    O Visual Studio adiciona o projeto Solution Explorer e exibe um novo formulário no designer.

Criando o Northwind Dataset

Nesta seção você criará um dataset chamado NorthwindDataSet.

Para criar o NorthwindDataSet

  1. Do dados menu, escolha fonte adicionar novos dados.

    O Assistente para Configuração da Fonte de Dados é aberto.

  2. Selecione banco de dados sobre o Escolher um tipo de fonte de dados página.

  3. Selecione uma conexão para o banco de dados de exemplo Northwind na lista de conexões disponíveis, ou clique em nova conexão se a conexão não está disponível na lista de conexões.

    Dica

    Se você estiver se conectando a um arquivo de banco de dados local, selecione não quando perguntado se você deseja adicionar o arquivo ao seu projeto.

  4. Clique em próximo sobre o Salvar cadeia de conexão no arquivo de configuração do aplicativo página.

  5. Expanda o tabelas nó e selecione o Customers tabela. O nome padrão para o conjunto de dados deve ser NorthwindDataSet.

  6. Clique em Concluir para adicionar o conjunto de dados para o projeto.

Criar um controle DataGridView de associação de dados

Nesta seção você criará um DataGridView arrastando o clientes item do fontes de dados window para seu formulário do Windows.

Para criar um controle DataGridView que está associado à tabela Customers

  1. Do dados menu, escolha Show Data Sources para abrir o janela fontes de dados.

  2. Do fontes de dados janela Expandir o NorthwindDataSet nó e selecione o clientes tabela.

  3. Clique na seta para baixo no nó da tabela e selecione DataGridView na lista suspensa.

  4. Arraste a tabela para uma área vazia do formulário.

    Um DataGridView controle denominado CustomersDataGridView e um BindingNavigator chamado CustomersBindingNavigator são adicionados ao formulário vinculado, o BindingSource que por sua vez é associado ao Customers na tabela a NorthwindDataSet.

Ponto de verificação

Agora você pode testar o formulário para certificar-se de que ele funciona como esperado até este ponto.

Para testar o formulário

  1. Pressione F5 para executar o aplicativo

    O formulário aparece com um DataGridView controle que é preenchido com dados do Customers tabela.

  2. Do Depurar menu, escolha parar depuração.

Tratamento de erros de simultaneidade

Como tratar erros depende de regras de negócio específicas que governam o aplicativo. Para este passo a passo, após uma violação de simultaneidade é gerada, a seguinte estratégia para lidar com o erro de simultaneidade será usada como uma ilustração:

O aplicativo apresentará ao usuário três versões do registro:

  • O registro atual no banco de dados.

  • O registro original carregado para o conjunto de dados.

  • As alterações propostas no dataset.

O usuário é então capaz de substituir o banco de dados com a versão proposta ou cancelar a atualização e atualizar o dataset com os novos valores do banco de dados.

Para habilitar o tratamento de erros de simultaneidade

  1. Crie um manipulador de erro personalizado.

  2. Exibir as opções para o usuário.

  3. Processe a resposta do usuário.

  4. Reenviar a atualização, ou redefinir os dados no conjunto de dados.

Adicionando código para tratar a exceção de simultaneidade

Quando você tenta executar uma atualização e uma exceção é gerada, você geralmente deseja fazer algo com as informações fornecidas pela exceção gerada.

Nesta seção você irá adicionar código que tentará atualizar o banco de dados e manipular qualquer DBConcurrencyException que pode ser gerada, bem como qualquer outra exceção.

Dica

O CreateMessage e ProcessDialogResults métodos serão adicionados posteriormente neste passo a passo.

Para adicionar o tratamento de erro para o erro de simultaneidade
  1. Adicione o seguinte código abaixo o Form1_Load método:

            private void UpdateDatabase()
            {
                try
                {
                    this.customersTableAdapter.Update(this.northwindDataSet.Customers);
                    MessageBox.Show("Update successful");
                }
                catch (DBConcurrencyException dbcx)
                {
                    DialogResult response = MessageBox.Show(CreateMessage((NorthwindDataSet.CustomersRow)
                        (dbcx.Row)), "Concurrency Exception", MessageBoxButtons.YesNo);
    
                    ProcessDialogResult(response);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error was thrown while attempting to update the database.");
                }
            }
    
        Private Sub UpdateDatabase()
    
            Try
                Me.CustomersTableAdapter.Update(Me.NorthwindDataSet.Customers)
                MsgBox("Update successful")
    
            Catch dbcx As Data.DBConcurrencyException
                Dim response As Windows.Forms.DialogResult
    
                response = MessageBox.Show(CreateMessage(CType(dbcx.Row, NorthwindDataSet.CustomersRow)),
                    "Concurrency Exception", MessageBoxButtons.YesNo)
    
                ProcessDialogResult(response)
    
            Catch ex As Exception
                MsgBox("An error was thrown while attempting to update the database.")
            End Try
        End Sub
    
  2. Substitua o CustomersBindingNavigatorSaveItem_Click método para chamar o UpdateDatabase método para que se pareça com o seguinte:

            private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                UpdateDatabase();
            }
    
        Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click
            UpdateDatabase()
        End Sub
    

Exibir as opções para o usuário

O código que você acabou de escrever chama o CreateMessage procedimento para exibir informações de erro para o usuário. Para este passo a passo, você usará uma caixa de mensagem para exibir as diferentes versões do registro para o usuário e permitir que o usuário escolha se deseja substituir o registro com as alterações ou cancelar a edição. Depois que o usuário seleciona uma opção (clicar um botão) na caixa de mensagem, a resposta é passada para o ProcessDialogResult método.

Para criar a mensagem a ser exibida para o usuário
  • Crie a mensagem, adicionando o seguinte código para o Editor de códigos. Digite este código abaixo o UpdateDatabase método.

            private string CreateMessage(NorthwindDataSet.CustomersRow cr)
            {
                return
                    "Database: " + GetRowData(GetCurrentRowInDB(cr), DataRowVersion.Default) + "\n" +
                    "Original: " + GetRowData(cr, DataRowVersion.Original) + "\n" +
                    "Proposed: " + GetRowData(cr, DataRowVersion.Current) + "\n" +
                    "Do you still want to update the database with the proposed value?";
            }
    
    
            //--------------------------------------------------------------------------
            // This method loads a temporary table with current records from the database
            // and returns the current values from the row that caused the exception.
            //--------------------------------------------------------------------------
            private NorthwindDataSet.CustomersDataTable tempCustomersDataTable = 
                new NorthwindDataSet.CustomersDataTable();
    
            private NorthwindDataSet.CustomersRow GetCurrentRowInDB(NorthwindDataSet.CustomersRow RowWithError)
            {
                this.customersTableAdapter.Fill(tempCustomersDataTable);
    
                NorthwindDataSet.CustomersRow currentRowInDb = 
                    tempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID);
    
                return currentRowInDb;
            }
    
    
            //--------------------------------------------------------------------------
            // This method takes a CustomersRow and RowVersion 
            // and returns a string of column values to display to the user.
            //--------------------------------------------------------------------------
            private string GetRowData(NorthwindDataSet.CustomersRow custRow, DataRowVersion RowVersion)
            {
                string rowData = "";
    
                for (int i = 0; i < custRow.ItemArray.Length ; i++ )
                {
                    rowData = rowData + custRow[i, RowVersion].ToString() + " ";
                }
                return rowData;
            }
    
        Private Function CreateMessage(ByVal cr As NorthwindDataSet.CustomersRow) As String
            Return "Database: " & GetRowData(GetCurrentRowInDB(cr), 
                                             Data.DataRowVersion.Default) & vbCrLf &
                   "Original: " & GetRowData(cr, Data.DataRowVersion.Original) & vbCrLf &
                   "Proposed: " & GetRowData(cr, Data.DataRowVersion.Current) & vbCrLf &
                   "Do you still want to update the database with the proposed value?"
        End Function
    
    
        '--------------------------------------------------------------------------
        ' This method loads a temporary table with current records from the database
        ' and returns the current values from the row that caused the exception.
        '--------------------------------------------------------------------------
        Private TempCustomersDataTable As New NorthwindDataSet.CustomersDataTable
    
        Private Function GetCurrentRowInDB(
            ByVal RowWithError As NorthwindDataSet.CustomersRow
            ) As NorthwindDataSet.CustomersRow
    
            Me.CustomersTableAdapter.Fill(TempCustomersDataTable)
    
            Dim currentRowInDb As NorthwindDataSet.CustomersRow =
                TempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID)
    
            Return currentRowInDb
        End Function
    
    
        '--------------------------------------------------------------------------
        ' This method takes a CustomersRow and RowVersion 
        ' and returns a string of column values to display to the user.
        '--------------------------------------------------------------------------
        Private Function GetRowData(ByVal custRow As NorthwindDataSet.CustomersRow,
            ByVal RowVersion As Data.DataRowVersion) As String
    
            Dim rowData As String = ""
    
            For i As Integer = 0 To custRow.ItemArray.Length - 1
                rowData &= custRow.Item(i, RowVersion).ToString() & " "
            Next
    
            Return rowData
        End Function
    

Processar a resposta do usuário

Você também precisará código para processar a resposta do usuário à caixa de mensagem. As opções são sobrescrever o registro atual no banco de dados com a alteração proposta ou abandonar as alterações locais e atualizar a tabela de dados com o registro no momento no banco de dados. Se o usuário escolher Sim, o Merge método for chamado com o preserveChanges argumento definido como true. Isso fará com que a tentativa de atualização seja bem-sucedida, pois a versão original do registro agora coincide com o registro no banco de dados.

Para processar o usuário de entrada da caixa de mensagem
  • Adicione o código a seguir abaixo do código adicionado na seção anterior.

            // This method takes the DialogResult selected by the user and updates the database 
            // with the new values or cancels the update and resets the Customers table 
            // (in the dataset) with the values currently in the database.
    
            private void ProcessDialogResult(DialogResult response)
            {
                switch (response)
                {
                    case DialogResult.Yes:
                        northwindDataSet.Merge(tempCustomersDataTable, true, MissingSchemaAction.Ignore);
                        UpdateDatabase();
                        break;
    
                    case DialogResult.No:
                        northwindDataSet.Merge(tempCustomersDataTable);
                        MessageBox.Show("Update cancelled");
                        break;
                }
            }
    
        ' This method takes the DialogResult selected by the user and updates the database 
        ' with the new values or cancels the update and resets the Customers table 
        ' (in the dataset) with the values currently in the database.
    
        Private Sub ProcessDialogResult(ByVal response As Windows.Forms.DialogResult)
    
            Select Case response
    
                Case Windows.Forms.DialogResult.Yes
                    NorthwindDataSet.Customers.Merge(TempCustomersDataTable, True)
                    UpdateDatabase()
    
                Case Windows.Forms.DialogResult.No
                    NorthwindDataSet.Customers.Merge(TempCustomersDataTable)
                    MsgBox("Update cancelled")
            End Select
        End Sub
    

Teste

Agora você pode testar o formulário para certificar-se de que ele se comporta conforme o esperado. Para simular uma violação de simultaneidade, você precisa alterar os dados no banco de dados depois de preencher o NorthwindDataSet.

Para testar o formulário

  1. Pressione F5 para executar o aplicativo.

  2. Depois que o formulário for exibido, deixá-lo funcionando e alterne para o Visual Studio IDE.

  3. Do exibição menu, escolha Server Explorer.

  4. Em Server Explorer, expanda a conexão de seu aplicativo está usando e, em seguida, expanda o tabelas nó.

  5. Clique com botão direito do clientes e selecione Mostrar dados da tabela.

  6. No primeiro registro (ALFKI) alterar o ContactName para Maria Anders2.

    Dica

    Navegue até uma linha diferente para confirmar a alteração.

  7. Alterne para o ConcurrencyWalkthroughdo formulário em execução.

  8. No primeiro registro no formulário (ALFKI), altere o ContactName para Maria Anders1.

  9. Clique o Salvar botão.

    O erro de simultaneidade é gerado e a caixa de mensagem é exibida.

  10. Clicar em não cancela a atualização e atualiza o dataset com os valores atualmente no banco de dados, enquanto clicar em Sim grava o valor proposto para o banco de dados.

Consulte também

Salvar dados no banco de dados