ADO.NET - Trabalhando com Múltiplas tabelas relacionados


Eu já escrevi diversos artigos sobre o acesso a dados com VB.NET usando ADO.NET. Por isso poderei as vezes até ser repetitivo ,  tenham portanto paciência comigo.

Abaixo uma pequena relação dos artigos que eu aconselho que você leia para saber conceitos básicos sobre o acesso a dados na plataforma .NET.

ADO.NET - Usando Transações.
ADO .NET - O Acesso aos dados
Meu Primeiro Acesso a Dados com o VB.NET
ADO.NET - Obtendo quantos registros um DataReader/DataSet vai retornar.
ADO.NET - A arquitetura de dados desconectada e a concorrência de dados
ADO.NET - Salvando e recuperando imagens de um banco de dados
ADO.NET - Criando uma livro de receitas
ADO.NET - Acessando fonte de dados - uma visão geral
VB .NET - ADO.NET - uma visão geral : o objeto DataSet
VB .NET - ADO.NET - Uma visão geral III : DataView
ASP.NET - Acessando e exibindo dados de uma fonte de dados com ADO.NET
ADO versus ADO.NET : o confronto !
ADO.NET - Obtendo o esquema de uma fonte de dados
VB .NET - ADO.NET - Uma visão geral II : DataTable
ADO.NET - Uma visão Geral I - Objeto Connection
ADO.NET - Operações básicas : Incluindo dados em uma tabela

 

Vamos agora ao assunto deste artigo. Vou mostrar como podemos trabalhar com múltiplas tabelas relacionadas usando ADO .NET.

 

Eu tenho comigo que um bom desenvolvedor deve possuir bons conhecimentos sobre banco de dados e modelagem de dados. Eu não pretendo me aprofundar neste assunto mas creio que é meu dever relembrar velhos conceitos que para muitos poderão ser maçantes mas que para outros que estão começando pode fazer a diferença entre entender tudo ou não entender nada.

 

Um banco de dados - database - é um repositório (não supositório ) especial usado para armazenar e recuperar informações.

 

Um banco de dados relacional é um tipo específico de banco de dados onde os dados estão separados em tabelas , e , as tabelas estão relacionadas umas as outras através de valores que chamamos chaves. Abaixo eu estou mostrando o relacionamento entre as tabelas do banco de dados Biblio.mdb. Este banco de dados é um banco Access e vem junto com o Office e com o VB.

 

Relacionamento do banco de dados Biblio.mdb :

 Um Editor(Publishers) possui muitos títulos (Titles)

Um autor(Authors) pode possuir muitos títulos também.

Figura 1.0 - Relacionamento das tabelas no banco de dados Biblio.mdb

 

Nota: O Access é um tipo de banco de dados de pequeno porte para soluções caseiras e para pequenas empresas . Ele é constituído de várias tabelas em um único arquivo mdb.Um arquivo Access tem a extensão .mdb.

 

Através do VB .NET podemos armazenar e recuperar informações em muitos tipos de banco de dados , dentre os quais eu cito :

Para fazer a conexão e o gerenciamento das informações com banco de dados o VB.NET utiliza ADO.NET.

 

ADO.NET armazena e transfere dados usando a XML - Extensible Markup Language ; através de dois tipos básicos de conexões :

Nota: Temos agora outros provedores como : ODBC .NET , MySQL .NET , Oracle .NET

 

Neste artigo eu vou usar o Access como exemplo por questão de simplicidade e por que nem todos possuem o SQL Server. Vou usar a versão Access 2000. A versão 2000 e 2002 usam a versão 4.0 do Jet DataBase Engine.(O motor do banco de dados)

 

Um banco de dados armazena dados sobre entidades individuais em tabelas separadas. Como exemplo de entidades presentes no banco de dados Biblio.mdb posso citar :Autores (Authors) , editores (Publishers) e títulos (Title).

 

Cada tabela é constituída de linhas e colunas:

 

- Linha (row) : representa uma informação sobre um Autor ou titulo ou editor. Também chamada de registro (record)

 

- Coluna (Column) - representa um campo de dados armazenados para cada autor, titulo ou editor. Ex: PubId , Title e ISBN.

 

Cada linha na tabela é identificada de forma única pelo campo chave primária. No caso acima as chaves para cada tabela estão representadas na figura 1.0 em negrito e são : PubId , ISBN , ISBN+Au_Id e Au_Id.

 

XML é um padrão da indústria usado para armazenar e transferir dados. Você não precisa saber como escrever XML para poder usar o VB e programar usando banco de dados. VB .NET gera automaticamente o XML que for necessário para sua aplicação.

 

Como XML armazena os dados na forma de texto identificados por tags como tags HTML podemos editar um arquivo XML com qualquer editor de textos . Isto facilita a transferência de dados na Web pois os dados não são barrados pelos firewalls.

 

Abaixo um exemplo de um arquivo XML. Vou representar neste código XML a tabela Authors. Esta tabela possui os seguintes linhas e colunas:(figura 2.0)

figura 2.0: A estrutura da tabela Authors

<?xml version="1.0" enconding = "UTF-8"?>
<dataroot xmlns:0d = "urn:schemas-microsoft-com:officedata">
   <Authors
      <AU_Id>1</AU_Id>
      <Author>Macoratti</Author>
      <Year Born>09081975</Year Born>
   </Authors>
   <Authors>
      <AU_Id>2</AU_Id>
      <Author>Jessica</Author>
      <Year Born>03071990</Year Born>
   </Authors>
</dataroot>

 

 

Nota : para saber mais sobre XML consulte a seção : XML/UML

 

Com ADO.NET podemos acessar banco de dados usando formulários criados no ambiente; Windows(Winforms) ou Web(WebForms). Ela fornece controles que você pode incluir em um formulário e que é usado para conectar e gerenciar dados em um banco de dados. Geralmente vinculamos (bound) as colunas das tabelas a estes controles.

 

Dentre estes controles podemos citar : Label , TextBox , ComboBox , ListBox , DataGrid e DataList.

 

As etapas básicas que você precisa fazer para acessar e gerenciar uma base de dados usando ADO.NET são :

  1. Configurar uma conexão - a conexão acessa o banco de dados

  2. Configurar um data adapter - Um Data Adapter manipula os dados retornados e atualizados e cria um DataSet. Um DataSet armazena linhas(registros) que foram retornadas.

  3. Incluir os controles no formulário e definir as propriedades dos controles que fazem a vinculação entre os controles e as colunas da tabela que esta no DataSet.

  4. Preencher o Dataset

Cada uma dessas etapas eu já abordei em artigos anteriores , e , como o procedimento e praticamente o mesmo , só mudando o nome da tabela , data adapter , dataset  eu não vou repetir neste artigo como fazer cada uma dessas etapas , vamos ir um pouco mais além e tratar das tabelas relacionadas em um DataSet.

 

Para trabalhar com tabelas relacionadas em um DataSet é necessário um conhecimento básico do namespace System.Data e como interagir com ele.

 

Os objetos a seguir são usados para facilitar o relacionamento em um DataSet:

Agora vamos criar uma aplicação no VB.NET . Nossa aplicação irá possuir uma conexão com uma base de dados access , um data adapter , um dataset que irá conter as tabelas relacionadas e alguns controles para exibir os dados.

 

1- Para criar uma nova aplicação do Tipo WIndows no VB .NET iremos fazer o seguinte :

2- Vamos agora criar uma conexão com o banco de dados Northwind.mdb (formato Access) para isto eu vou usar o Server Explorer.

 

 

Vamos criar o relacionamento entre as tabelas Clientes e Pedidos. No banco de dados temos que o relacionamento é o seguinte :

 

- Temos aqui o tipo de relacionamento do tipo UM-Para-Muitos

- Um cliente pode ter muitos pedidos

- O relacionamento entre as tabelas e feita pela chave CódigoDoCliente das duas tabelas.

 

 

Para criar este relacionamento entre as tabelas faça o seguinte :

Após confirmar a operação se você clicar no arquivo dsNorthwind.xsd irá visualizar o seguinte:

 

Esta tudo pronto para visualizarmos os dados no formulário ; para isto vou trabalhar com os controles ComboBox , ListBox e Rich text box , então vamos lá...

 

Vamos por o projeto para funcionar :

 

1- Vamos carregar a combobox de forma a exibir o nome da empresa para isto selecione a combobox e defina as seguintes propriedades:

 

  • DataSource = DsNorthwind1

  • DisplayMember = clientes.NomeDaEmpresa

  • ValueMember = Clientes.CódigoDoCliente

(Veja figura ao lado)

 

Agora vamos preencher as tabelas com dados para isto vamos ter que incluir código no evento Load do formulário:

 

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'desabilita as constraints no dataset
        DsNorthwind1.EnforceConstraints = False
        'preenche as tabelas com dados
        daPedidos.Fill(DsNorthwind1)
        daClientes.Fill(DsNorthwind1)
        'habilita as constraints novamente
        DsNorthwind1.EnforceConstraints = True
    End Sub

 

Salve o projeto e rode a aplicação pressionando F5. Você verá a combo carregada com os nomes das empresas:

 

 

Vamos implementar a navegação entre os registros relacionados das tabelas. Para acessar dados entre tabelas relacionadas em uma relação UM-Para-Muitos você deve selecionar uma linha(registro)  e a seguir retornar os registros relacionados invocando o método GetChildRows ou o método GeParentRow passando-os no apropriados DataRelation. (GetChildRows retorna os dados em array de objetos DataRow e GetParentRow retorna uma única linha)

 

Para mostrar isto vamos incluir código para retornar todos os pedidos (Child rows) para o cliente selecionado na combobox ; o código será incluindo no evento SelectedIndexChanged da combobox. Quando houver alteração de cliente na combobox o evento ComboBox.SelectedIndexChanged irá ser disparado e iremos preencher o listbox com os pedidos para cada cliente selecionado.

 

Podemos chamar o método GetChildRows baseado no cliente selecionado de forma a atribuir todos os pedidos relacionados a um array de data rows chamado draPedidos.  Para implementar isto faça o seguinte:

   Private Sub cboClientes_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 
Handles cboClientes.SelectedIndexChanged
        'declara uma string para manipular os clientes selecionados
        Dim codigoClienteSelecionado As String
        codigoClienteSelecionado = cboClientes.SelectedValue.ToString()
        'declara um data row para manipular os registros do clientes selecionado
        Dim drClienteSelecionado As DataRow
        drClienteSelecionado = DsNorthwind1.Clientes.FindByCódigoDoCliente(codigoClienteSelecionado)
        'declare um array de data rows para manipular os registros relacionados
        Dim draPedidos() As DataRow
        'em getChildRows - ClentesPedidos - é o nome dado a relação criada
        draPedidos = drClienteSelecionado.GetChildRows("ClientesPedidos")
        'exibe a quantidade de pedidos na label
        lblinfo.Text = draPedidos.Length & " Pedidos para " & codigoClienteSelecionado
    End Sub

 

 

Salve a aplicação e rode o projeto. Você irá ver a quantidade de pedidos relacionados a cada cliente sendo exibidos na label no formulário.

 

Como já temos os registros de um cliente selecionado armazenado em um array de data rows vamos exibí-los no formulário. A aplicação deverá interagir através do array  com os dados retornados através do método GetChildRows e incluir o NúmeroDoPedido para cada registro relacionado como um item individual no listbox. O código para fazer este serviço deverá ser incluido no evento cboClientes_SelectedIndexChanged ; Abaixo o código completo com a inclusão destacada:

 

   Private Sub cboClientes_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 
Handles cboClientes.SelectedIndexChanged
        'declara uma string para manipular os clientes selecionados
        Dim codigoClienteSelecionado As String
        codigoClienteSelecionado = cboClientes.SelectedValue.ToString()
        'declara um data row para manipular os registros do clientes selecionado
        Dim drClienteSelecionado As DataRow
        drClienteSelecionado = DsNorthwind1.Clientes.FindByCódigoDoCliente(codigoClienteSelecionado)
        'declare um array de data rows para manipular os registros relacionados
        Dim draPedidos() As DataRow
        'em getChildRows - ClentesPedidos - é o nome dado a relação criada
        draPedidos = drClienteSelecionado.GetChildRows("ClientesPedidos")
        'exibe a quantidade de pedidos na label
        lblinfo.Text = draPedidos.Length & " Pedidos para " & codigoClienteSelecionado
 

         'limpa o listbox e o richtextbox

          lstPedidos.Items.Clear()

          rtbDetalhes.Text = ""
 

         'exibe o numero de cada pedido do cliente selecionado

          Dim drPedidos As DataRow

          For Each drPedidos In draPedidos

               lstPedidos.Items.Add(drPedidos("NúmeroDoPedido"))
         
Next

 
    End Sub

 

 

Ao rodar o projeto e selecionar um cliente o número de cada pedido do cliente selecionado será exibido na listbox.

 

Para terminar precisamos exibir os detalhes do pedido selecionado no controle RichTextBox. Para fazer isto vamos ter que incluir mais duas tabelas ao DataSet existente e criar um novo objeto DataRelation.

 

Precisamos agora criar os relacionamentos entre as tabelas Produtos e Detalhes do Pedido recém incluídas.

 

Na janela - Edit Relation - configure as propriedades conforme figura abaixo:

 

 

Agora precisamos incluir o código para preencher as tabelas produtos e detalhes do pedido. No evento Load do formulário exibimos o código completo com o código incluído destacado:

 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


'desabilita as constraints no dataset

DsNorthwind1.EnforceConstraints = False


'preenche as tabelas com dados

daPedidos.Fill(DsNorthwind1)

daClientes.Fill(DsNorthwind1)

 

'habilita as constraints novamente

DsNorthwind1.EnforceConstraints = True

 

'preenchendo as tableas produtos e detalhes do pedidos

daDetalhesPedidos.Fill(DsNorthwind1)

daProdutos.Fill(DsNorthwind1)

 

End Sub

 

Vamos finalmente exibir os detalhes dos pedidos no controle RichTextBox. O código para fazer isto invoca o método GetChildRows baseado no pedido selecionado na listbox. Todos os registros relacionados na tabela Detalhes dos Pedidos são atribuidos a um array de data rows que vou chamar de draDetalhesPedidos. O conteúdo de cada data row é exibido então no rich text box.

Private Sub lstPedidos_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstPedidos.SelectedIndexChanged

 

'limpa o controle richtextbox

rtbDetalhes.Clear()

 

'declara um inteiro para tratar o Numero do pedido selecionado

Dim codigoPedidoSelecionado As Integer

'efetua uma conversão explicita (casting) do item selecionado para um integer

codigoPedidoSelecionado = CType(lstPedidos.SelectedItem, Integer)

 

'declara um data row para tratar o pedido selecionado

Dim drPedidoSelecionado As DataRow

drPedidoSelecionado = DsNorthwind1.Pedidos.FindByNúmeroDoPedido(codigoPedidoSelecionado)

 

'declara um array de data rows a fim de tratar os registros relacionados

Dim draDetalhesPedido() As DataRow

draDetalhesPedido = drPedidoSelecionado.GetChildRows("ClientesDetalhesDoPedido")

 

Dim detalhes As String

Dim drDetalhes As DataRow

Dim dcDetalhes As DataColumn

 

For Each drDetalhes In draDetalhesPedido

   For Each dcDetalhes In drDetalhes.Table.Columns

      detalhes &= dcDetalhes.ColumnNa

me & " : " & drDetalhes(dcDetalhes).ToString() & ControlChars.CrLf

   Next

Next

rtbDetalhes.Text = detalhes

End Sub

 

Agora rode o projeto e você verá todas as funcionalidades implementadas funcionando.

 

 

Parabéns!  você já sabe trabalhar com tabelas relacionadas no VB.NET e percebeu que não é tão complicado assim. Cabe a você expandir seus conhecimentos melhorando a interface usada no exemplo.

 

Em um próximo artigo irei falar de tabelas com relacionamentos muitos para muitos e em como tratar isto no VB.NET, até lá... .

Salmos 19:1 Os céus proclamam a glória de Deus e o firmamento anuncia a obra das suas mãos.

Salmos 19:2 Um dia faz declaração a outro dia, e uma noite revela conhecimento a outra noite.

Salmos 19:3 Não há fala, nem palavras; não se lhes ouve a voz.


Veja os Destaques e novidades do SUPER DVD VB (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Veja mais sistemas completos para a plataforma .NET no Super DVD .NET , confira...

Quer aprender C# ??

Chegou o Super DVD C# com exclusivo material de suporte e vídeo aulas com curso básico sobre C#
 

   Gostou ?   Compartilhe no Facebook    Compartilhe no Twitter

Referências:


José Carlos Macoratti