VB.NET 2008 - TableAdapterManager - Atualização de tabelas relacionadas


O TableAdapterManager é um novo componente presente no VS 2008 que atua sobre datasets tipados e TableAdapters e permite a atualização de dados em tabelas relacionadas(Atualização hierárquica) de uma forma mais fácil. Na versão anterior era necessário a inclusão de código para realizar esta tarefa corretamente.

A atualização hierárquica é o processo de atualização dos dados modificados em tabelas relacionadas em um dataset tipado pela utilização do novo componente TableAdapterManager.

O TableAdapterManager usa o relacionamento da chave primária entre as tabelas para determinar corretamente a ordem na qual deve enviar os Inserts, Updates e Deletes do DataSet para o banco de dados sem violar as restrições da chave-primária (integridade referencial) no banco de dados.

As restrições das chaves primárias são as regras de consistência existentes no banco de dados que controlam o comportamento para inclusão, atualização e exclusão de registros relacionados. É a integridade referencial que previne que os registros de uma tabela pai sejam deletados enquanto ainda existirem registros na tabela filha relacionada.

Salvar dados de tabelas relacionados é uma tarefa mais complexa pois os comandos para inclusão, atualização e exclusão para cada tabela relacionada tem que ser executadas em um ordem específica para evitar a violação na integridade referencial definida no banco de dados.

Considere uma aplicação que controla Clientes e Pedidos. Se você tiver que excluir um cliente existente , você primeiro terá que excluir todos os pedidos deste cliente. Se você estiver incluindo um novo cliente (com um pedido) primeiro você tem que incluir o cliente e depois incluir o pedido devido as restrições impostas pela chave primária existente entre as tabelas. Dessa forma você deve efetuar as operações na ordem correta para manter a integridade referencial e evitar conflitos com as restrições da chave primária.

A classe TableAdapterManager é gerada quando você cria um dataset tipado em um projeto. Na verdade é a propriedade Hierarchical Update do dataset que determina se um TableAdpaterManager será criado ou não. Se o valor da propriedade for definido como True ele será criado e o código para atualizar atualização hierárquica em tabelas relacionadas é gerado também.

Se a propriedade for definida como False o TableAdapterManager não será criado. Neste caso quando você for salvar os dados em tabelas relacionadas você deverá usar código para indicar a ordem na qual as operações de inclusão , atualização ou delete devem ser realizadas de forma a não violar a integridade referencial.

No VS 2008 quando você cria um dataset tipado por padrão a propriedade Hierarchical Update é definida como True. Nas versões anteriores a mesma operação define esta propriedade como False.

A seguir vou mostrar um exemplo passo a passo de como usar o TableAdapterManager para efetuar atualização em tabelas relacionadas.

Para acompanhar este exemplo você pode usar o Visual Basic 2008 Express Edition ou o VS 2008 e deve possuir o banco de dados SQL Server 2005 Express Edition instalado bem como o banco de dados de exemplo Northwind.mdf.

Usando TableAdapterManager

Abra o VB 2008 Express Edition e crie um novo projeto a partir do menu File -> New Project com o nome : usandoTableAdapterManager;

Selecione o template Windows Forms Application e clique em OK;

A seguir vamos criar um DataSet contendo as tabelas Customer e Orders do banco de dados Northwind.mdf pois esta tabelas estão relacionadas pela

No menu Data -> Add New Data Source abra o Data Source Configuration Wizard;

Selecione DataBase na janela Choose a Data Source Type e clique em Next>;

Defina uma conexão com o banco de dados Northwind.mdf e clique em Next>;

Salve a string de conexão com o nome padrão e clique em Next>;

Expanda o nó Tables e selecione as tabelas Orders e Customers e clique em Finish>;

Selecione o formulário form1.vb e abra a janela Data Source;

A seguir expanda o nó Customers e altere o modo para Details conforme figura I;

 
Figura I - Customers   Figura II - Orders

Agora expanda o nó Orders e selecione o modo DataGridView conforme figura II.

Agora vamos arrastar os nós Customers e Orders , nesta ordem, a partir da janela Data Sources para o formulário conforme o leiaute abaixo:

Veja que além dos objetos BindingSource , TableAdapter foi gerado um TableAdapterManager.

Selecione o DataSet e verifique na janela de propriedades que a propriedade Hierarquical Update esta definida como True.

Vamos agora espiar o código gerado no formulário form1.vb:

O código é gerado para o evento Load do formulário form1 e para o evento Click do botão Salvar do BindingNavigator.

Após chamar o método Validate() é usado o método EndEdit para o CustomersBindingSource. Quando o método EndEdit é usado ele aplica as alterações pendentes a fonte de dados relacionada. Esta operação deve ser feita antes de salvar os dados para o banco de dados.

No evento Click do botão Salvar temos o componente TableAdapterManager usando o método UpdateAll para o dataset que contém as tabelas relacionadas, isso irá enviar as atualizações de todas as tabelas do DataSet para o banco de dados.

Como você pode notar foi gerado código apenas para a tabela Customers, a primeira tabela que foi arrastada para o formulário a partir da janela Data Sources. Devemos então incluir o código para aplicar as alterações pendentes também para a tabela Orders através do BindingSource. O código ficaria assim:

    Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _ 
CustomersBindingNavigatorSaveItem.Click

        Me.Validate()
        Me.CustomersBindingSource.EndEdit()
        Me.OrdersBindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.NORTHWNDDataSet)

    End Sub

Além de efetivar as alterações realizadas em tabelas filhas relacionadas antes de salvar os dados no banco de dados devemos também efetivar novos registros criados na tabela Pai antes de incluir um novo registro relacionado na tabela Filha, ou seja, devemos primeiro efetivar as alterações para um novo Cliente no DataSet antes de incluir um novo Pedido. Para realizar tal tarefa usamos o evento BindingSource.AddingNew para a tabela filha Orders:

    Private Sub OrdersBindingSource_AddingNew(ByVal sender As System.Object, ByVal e As System.ComponentModel.AddingNewEventArgs) _ 
Handles OrdersBindingSource.AddingNew

        Me.CustomersBindingSource.EndEdit()

    End Sub

O último passo é verificar se a propriedade Hierarchical Update do DataSet esta definida como True, feito isso já podemos testar a aplicação.

Executando a aplicação pressionando F5 vamos realizar algumas alterações nos registros de cada tabela e em seguida vamos incluir um novo Cliente (Customer) e um novo pedido para este cliente e salvar os dados clicando no botão Salvar.

- Alterando alguns dados nas duas tabelas;

- Incluindo um novo Cliente e em seguida um novo pedido para este cliente;

Clicamos no botão Salvar.

Vamos agora verificar no banco de dados se as informações foram salvas corretamente:

- Abrindo a Tabela Customers vemos o novo cliente incluído:

- Abrindo a Tabela Orders vemos o pedido para o cliente MAC incluido:

Com isso atestamos que o procedimento é funcional o que nos livra de um grande trabalho a ser realizado.

O TableAdapterManager veio facilitar a vida do desenvolvedor permitindo a atualização de tabelas relacionadas de forma mais simples mas o desenvolvedor deve atentar para o fato de que o seu funcionamento depende de um modelo de dados normalizado corretamente com as definições dos relacionamento entre as tabelas e das chaves primárias feita de forma criteriosa.

Eu sei é apenas VB.NET mas eu gosto.


José Carlos Macoratti