Partilhar via


Atualização hierárquica no desenvolvimento do .NET Framework

Observação

A DataSet classe e as classes relacionadas são tecnologias herdadas do .NET Framework do início dos anos 2000 que permitem que os aplicativos trabalhem com dados na memória enquanto os aplicativos estão desconectados do banco de dados. As tecnologias são especialmente úteis para aplicativos que permitem aos usuários modificar dados e manter as alterações de volta ao banco de dados. Embora os conjuntos de dados sejam uma tecnologia comprovadamente bem-sucedida, a abordagem recomendada para novos aplicativos .NET é usar o Entity Framework Core. O Entity Framework fornece uma maneira mais natural de trabalhar com dados tabulares como modelos de objeto e tem uma interface de programação mais simples.

Atualização hierárquica refere-se ao processo de salvar dados atualizados (de um conjunto de dados com duas ou mais tabelas relacionadas) de volta a um banco de dados, mantendo regras de integridade referencial. Integridade referencial refere-se às regras de consistência fornecidas pelas restrições em um banco de dados que controlam o comportamento de inserir, atualizar e excluir registros relacionados. Por exemplo, é a integridade referencial que impõe a criação de um registro de cliente antes de permitir que pedidos sejam criados para esse cliente. Para obter mais informações sobre relações em conjuntos de dados, consulte Relações em conjuntos de dados.

O recurso de atualização hierárquica usa a TableAdapterManager para gerenciar os TableAdapters em um conjunto de dados tipado. O TableAdapterManager componente é uma classe gerada pelo Visual Studio, não um tipo .NET. Quando você arrasta uma tabela da janela Fontes de dados para uma página do Windows Form ou WPF, o Visual Studio adiciona uma variável do tipo TableAdapterManager ao formulário ou página e você a vê no designer na bandeja do componente. Para obter informações detalhadas sobre a TableAdapterManager classe, consulte a seção Referência TableAdapterManager de TableAdapters.

Por padrão, um conjunto de dados trata tabelas relacionadas como "somente relações", o que significa que ele não impõe restrições de chave estrangeira. Você pode modificar essa configuração em tempo de design usando o Dataset Designer. Selecione a linha de relação entre duas tabelas para abrir a caixa de diálogo Relação . As alterações feitas aqui determinarão como o TableAdapterManager se comporta quando ele envia as alterações nas tabelas relacionadas de volta para o banco de dados.

Habilitar atualização hierárquica em um conjunto de dados

Por padrão, a atualização hierárquica é habilitada para todos os novos conjuntos de dados adicionados ou criados em um projeto. Ative ou desative a atualização hierárquica definindo a propriedade Atualização Hierárquica de um conjunto de dados tipado em O conjunto de dados como Verdadeiro ou Falso:

Configuração de atualização hierárquica

Criar uma nova relação entre tabelas

Para criar uma nova relação entre duas tabelas, no Designer de Conjunto de Dados, selecione a barra de título de cada tabela, clique com o botão direito do mouse e selecione Adicionar relação.

Atualização hierárquica adicionar menu de relação

Compreender restrições de chave estrangeira, atualizações em cascata e exclusões

É importante entender como as restrições de chave estrangeira e o comportamento em cascata no banco de dados são criados no código do conjunto de dados gerado.

Por padrão, as tabelas de dados em um conjunto de dados são geradas com relações (DataRelation) que correspondem às relações no banco de dados. No entanto, a relação no conjunto de dados não é gerada como uma restrição de chave estrangeira. O DataRelation é configurado como Somente relação sem UpdateRule ou DeleteRule em vigor.

Por padrão, as atualizações em cascata e as exclusões em cascata são desativadas mesmo se a relação de banco de dados estiver definida com atualizações em cascata ou exclusões em cascata ativadas. Por exemplo, criar um novo cliente e um novo pedido e, em seguida, tentar salvar os dados pode causar um conflito com as restrições de chave estrangeira definidas no banco de dados. Para obter mais informações, consulte Desativar restrições ao preencher um conjunto de dados.

Definir a ordem para executar atualizações

Definir a ordem para executar atualizações define a ordem das inserções, atualizações e exclusões individuais necessárias para salvar todos os dados modificados em todas as tabelas de um conjunto de dados. Quando a atualização hierárquica está habilitada, as inserções são executadas primeiro, depois as atualizações e, em seguida, as exclusões. O TableAdapterManager fornece uma propriedade UpdateOrder que pode ser definida para executar primeiro as atualizações, depois as inserções, e por fim as eliminações.

Observação

É importante entender que a ordem de atualização é tudo incluído. Ou seja, quando as atualizações são executadas, inserções e, em seguida, exclusões são realizadas para todas as tabelas no conjunto de dados.

Para definir a UpdateOrder propriedade, depois de arrastar itens da janela Fontes de Dados para um formulário, selecione a TableAdapterManager na bandeja do componente e defina a UpdateOrder propriedade na janela Propriedades .

Criar uma cópia de backup de um conjunto de dados antes de executar uma atualização hierárquica

Quando você salva dados (chamando o TableAdapterManager.UpdateAll() método), o TableAdapterManager tenta atualizar os dados para cada tabela em uma única transação. Se qualquer parte da atualização de qualquer tabela falhar, toda a transação será revertida. Na maioria das situações, a reversão retorna seu aplicativo ao seu estado original.

No entanto, às vezes você pode querer restaurar o conjunto de dados a partir da cópia de backup. Um exemplo disso pode ocorrer quando você estiver usando valores de incremento automático. Por exemplo, se uma operação de salvamento não for bem-sucedida, os valores de incremento automático não serão redefinidos no conjunto de dados e o conjunto de dados continuará a criar valores de incremento automático. Isso deixa uma lacuna na numeração que pode não ser aceitável em seu aplicativo. Em situações em que isso é um problema, o TableAdapterManager fornece uma BackupDataSetBeforeUpdate propriedade que substitui o conjunto de dados existente por uma cópia de backup se a transação falhar.

Observação

A cópia de backup está apenas na memória enquanto o TableAdapterManager.UpdateAll método está em execução. Portanto, não há acesso programático a esse conjunto de dados de backup porque ele substitui o conjunto de dados original ou sai do escopo assim que o método termina de TableAdapterManager.UpdateAll ser executado.

Modificar o código de salvamento gerado para executar a atualização hierárquica

Salve as alterações das tabelas de dados relacionadas no conjunto de dados para o banco de dados chamando o TableAdapterManager.UpdateAll método e passando o nome do conjunto de dados que contém as tabelas relacionadas. Por exemplo, execute o TableAdapterManager.UpdateAll(NorthwindDataset) método para enviar atualizações de todas as tabelas em NorthwindDataset para o banco de dados back-end.

Depois de soltar os itens da janela Fontes de dados, o código é automaticamente adicionado ao evento Form_Load para preencher cada tabela com os métodos TableAdapter.Fill. O código também é adicionado ao evento de clique do botão Salvar para BindingNavigator salvar dados do conjunto de dados de volta ao banco de dados (através do método TableAdapterManager.UpdateAll).

O código de salvamento gerado também contém uma linha de código que chama o CustomersBindingSource.EndEdit método. Mais especificamente, ele chama o método EndEdit do primeiro BindingSource que é adicionado ao formulário. Em outras palavras, esse código é gerado apenas para a primeira tabela que é arrastada da janela Fontes de Dados para o formulário. A EndEdit chamada confirma todas as alterações que estão em processo em quaisquer controles ligados a dados que estão sendo editados no momento. Portanto, se um controlo vinculado a dados ainda tiver foco e clicar no botão Salvar, todas as edições pendentes nesse controlo serão confirmadas antes do salvamento real (o método TableAdapterManager.UpdateAll).

Observação

O Dataset Designer adiciona apenas o BindingSource.EndEdit código para a primeira tabela que é solta no formulário. Portanto, você precisa adicionar uma linha de código para chamar o BindingSource.EndEdit método para cada tabela relacionada no formulário. Para este passo a passo, isso significa que você precisa adicionar uma chamada ao OrdersBindingSource.EndEdit método.

  1. Clique duas vezes no botão Salvar para BindingNavigator abrir o Form1 no Editor de códigos .

  2. Adicione uma linha de código para chamar o OrdersBindingSource.EndEdit método após a linha que chama o CustomersBindingSource.EndEdit método. O código no evento clique no botão Salvar deve ser semelhante ao seguinte:

    this.Validate();
    this.customersBindingSource.EndEdit();
    this.ordersBindingSource.EndEdit();
    this.tableAdapterManager.UpdateAll(this.northwindDataSet);
    

Além de confirmar alterações em uma tabela filho relacionada antes de salvar dados em um banco de dados, talvez seja necessário confirmar registros pai recém-criados antes de adicionar novos registros filho a um conjunto de dados. Em outras palavras, talvez seja necessário adicionar o novo registro pai (Customer) ao conjunto de dados antes que restrições de chave estrangeira permitam que novos registros filho (Orders) sejam adicionados ao conjunto de dados. Para fazer isso, você pode usar o evento filho BindingSource.AddingNew .

Observação

Se você precisa confirmar novos registros pai depende do tipo de controle usado para vincular à sua fonte de dados. Nesta explicação passo a passo, você usa controles individuais para vincular à tabela pai. Isto requer um código adicional para confirmar o novo registo pai. Se, em vez disso, os registros pai fossem exibidos em um controle de vinculação complexo como o DataGridView, essa chamada adicional EndEdit para o registro pai não seria necessária. Isso ocorre porque a funcionalidade subjacente de ligação de dados do controlo lida com a confirmação dos novos registos.

Para adicionar código para confirmar registos principais no conjunto de dados antes de adicionar novos registos secundários.

  1. Crie um manipulador de eventos para o evento OrdersBindingSource.AddingNew.

    • Abra o Form1 no modo de design, selecione OrdersBindingSource na bandeja do componente, selecione Eventos na janela Propriedades e clique duas vezes no evento AddingNew .
  2. Adicione uma linha de código ao manipulador de eventos que chama o CustomersBindingSource.EndEdit método. O código no manipulador de OrdersBindingSource_AddingNew eventos deve ser semelhante ao seguinte:

    this.customersBindingSource.EndEdit();
    

Referência do TableAdapterManager

Por padrão, uma TableAdapterManager classe é gerada quando você cria um conjunto de dados que contém tabelas relacionadas. Para evitar que a classe seja gerada, altere o Hierarchical Update valor da propriedade do conjunto de dados para false. Quando arrastas uma tabela que tem uma relação para a superfície de design de uma página do Windows Form ou WPF, o Visual Studio declara uma variável membro da classe. Se você não usar databinding, terá que declarar manualmente a variável.

A TableAdapterManager classe não é um tipo .NET. Portanto, você não pode procurá-lo na documentação. Ele é criado durante a fase de design como parte do processo de criação do conjunto de dados.

A seguir estão os métodos e propriedades usados com freqüência da TableAdapterManager classe:

Membro Descrição
UpdateAll método Salva todos os dados de todas as tabelas de dados.
BackUpDataSetBeforeUpdate propriedade Determina se deve ser criada uma cópia de backup do conjunto de dados antes de executar o método TableAdapterManager.UpdateAll. Booleano.
tableNameTableAdapter propriedade Representa um TableAdapter. O TableAdapterManager gerado contém uma propriedade para cada TableAdapter que gerencia. Por exemplo, é gerado um conjunto de dados com uma tabela de Clientes e Pedidos com um TableAdapterManager que contém as propriedades CustomersTableAdapter e OrdersTableAdapter.
UpdateOrder propriedade Controla a ordem dos comandos individuais de inserção, atualização e exclusão. Defina isso como um dos valores na TableAdapterManager.UpdateOrderOption enumeração.

Por padrão, o UpdateOrder é definido como InsertUpdateDelete. Isso significa que inserções, atualizações e exclusões são executadas para todas as tabelas no conjunto de dados.