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:
Criar um novo Windows Application projeto.
Criar um novo conjunto de dados com base em Northwind
Customers
tabela.Criar um formulário com um DataGridView para exibir os dados.
Preencher um dataset com dados a partir de
Customers
tabela no banco de dados Northwind.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.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.
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:
- Acesso ao banco de dados de exemplo Northwind com permissão para executar atualizações. Para obter mais informações, consulte Como instalar bancos de dados de exemplo.
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
Do arquivo menu, crie um novo projeto.
Selecione uma linguagem de programação a tipos de projeto painel.
Selecione Windows Application no modelos painel.
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
Do dados menu, escolha fonte adicionar novos dados.
O Assistente para Configuração da Fonte de Dados é aberto.
Selecione banco de dados sobre o Escolher um tipo de fonte de dados página.
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.
Clique em próximo sobre o Salvar cadeia de conexão no arquivo de configuração do aplicativo página.
Expanda o tabelas nó e selecione o
Customers
tabela. O nome padrão para o conjunto de dados deve serNorthwindDataSet
.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
Do dados menu, escolha Show Data Sources para abrir o janela fontes de dados.
Do fontes de dados janela Expandir o NorthwindDataSet nó e selecione o clientes tabela.
Clique na seta para baixo no nó da tabela e selecione DataGridView na lista suspensa.
Arraste a tabela para uma área vazia do formulário.
Um DataGridView controle denominado
CustomersDataGridView
e um BindingNavigator chamadoCustomersBindingNavigator
são adicionados ao formulário vinculado, o BindingSource que por sua vez é associado aoCustomers
na tabela aNorthwindDataSet
.
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
Pressione F5 para executar o aplicativo
O formulário aparece com um DataGridView controle que é preenchido com dados do
Customers
tabela.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
Crie um manipulador de erro personalizado.
Exibir as opções para o usuário.
Processe a resposta do usuário.
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
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
Substitua o
CustomersBindingNavigatorSaveItem_Click
método para chamar oUpdateDatabase
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
Pressione F5 para executar o aplicativo.
Depois que o formulário for exibido, deixá-lo funcionando e alterne para o Visual Studio IDE.
Do exibição menu, escolha Server Explorer.
Em Server Explorer, expanda a conexão de seu aplicativo está usando e, em seguida, expanda o tabelas nó.
Clique com botão direito do clientes e selecione Mostrar dados da tabela.
No primeiro registro (
ALFKI
) alterar oContactName
paraMaria Anders2
.Dica
Navegue até uma linha diferente para confirmar a alteração.
Alterne para o
ConcurrencyWalkthrough
do formulário em execução.No primeiro registro no formulário (
ALFKI
), altere oContactName
paraMaria Anders1
.Clique o Salvar botão.
O erro de simultaneidade é gerado e a caixa de mensagem é exibida.
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.