Curso de ADO.NET e BDP - Parte VIII

Acesso a dados no Delphi 8 for .NET

 

Parte VIII – DataSets e DataTables

Até agora conhecemos todos os recursos oferecidos pelos Managed Providers , mais especificamente o provider da Borland (BDP). Esses componentes se encarregam de realizar operações diretamente no BD, como conexão, execução de comandos, transações etc.

Neste artigo começaremos a estudar o segundo grupo de componentes da arquitetura ADO.NET, que não dependem de uma conexão com o BD, pois atuam sobre dados que estão na memória (cache) da aplicação cliente. O DataSet e o DataTable são sem sombra de dúvida os dois principais componentes da arquitetura. De fato, a forma como o ADO.NET foi projetado, com base no conceito de “datasets desconectados”, delega importantes tarefas e atribuições para estes componentes

O objeto DataSet (acessível através do namespace System.Data ) tem um importante papel na arquitetura ADO.NET. Seu objetivo é armazenar dados fornecidos por um DataAdapter , fazendo uma cache local, em memória e desconectada do banco de dados (por meio de objetos DataTable , visto a seguir)

Um DataSet , juntamente com os objetos DataTable , DataColumn , DataRow , DataView e DataRelation , faz parte do segundo grupo de componentes da arquitetura ADO.NET, os Content Components (chamados ainda de “desconectados”). Você pode utilizar um DataSet com qualquer um dos Managed Providers fornecidos, como SQL e OLE DB, ou BDP no caso deste curso.

Um DataSet não armazena dados vindos somente de um banco de dados (trazidos por um DataAdapter ), mas pode ser utilizado para ler dados de um arquivo XML, para obter dados de um servidor de aplicação, de uma planilha, ou ainda dados gerados em memória. Esse comportamento é exatamente o mesmo do ClientDataSet do DataSnap.

Uma das principais diferenças de um DataSet para um ClientDataSet do DatSnap é que um DataSet pode fazer cache de mais de uma tabela ao mesmo tempo. Ele possui internamente uma coleção de objetos DataTable . Falando em um nível mais alto, imagine um DataSet como uma “coleção de ClientDataSets ”.

No ClientDataSet , por mais que sua instrução SQL possa trazer dados de várias tabelas usando um join , o que você obtém são dados em formato tabular que se parecem com uma única tabela do banco de dados. Já um DataSet do ADO.NET se comporta como um “mini banco de dados”. Ou seja, ele é capaz de gerenciar várias tabelas, relacionamentos, índices e visões dentro de uma mesma estrutura.

A figura abaixo mostra a estrutura de um DataSet:

 

 

Para quem está acostumado a usar os DataSets da VCL, é bom saber desde já que a maneira como o .NET Framework gerencia o cursor local de dados é completamente diferente. Em outras palavras, você não “navegará pelos registros de um DataSet” conforme está acostumado a fazer em aplicações de BD na VCL. No .NET, classes especializadas (estudadas mais adiante neste curso) se encarregam desse papel. O DataTable nada mais é que uma matriz de dados, onde as colunas são os campos e as linhas os registros. Não já o conceito de “registro atual”.

Neste primeiro exemplo veremos como realizar operações básicas sobre um DataTable , como fazer uma varredura examinando seus registros, excluir, alterar, adicionar e localizar registros etc.

Observe que não utilizaremos ainda o recurso de DataBindings , de forma que acessaremos os dados do DataTable diretamente (no “braço”). DataBindings é discutido mais adiante neste curso.

Configurando o acesso a dados e controles do formulário

Inicie uma nova aplicação do tipo Windows Forms Application . Expanda a conexão Employee no Data Explorer e arraste a tabela Country para o designer. Isso cria um BdpConnection e um BdpDataAdapter . Coloque um DataSet e aponte a propriedade DataSet do BdpDataAdapter para esse componente. Ative o BdpDataAdapter .

Coloque no formulário um ListView , sete Buttons , dois TextBoxes , três Labels e três ComboBoxes. Ajuste-os conforme mostrado na figura a seguir:

 

 

Varrendo registros

No evento Click do botão Listar digite o seguinte:

var

  Table: DataTable;

  Row: DataRow;

  Col: DataColumn;

  Column: DataColumn;

  i,j: integer;

  LvItem: ListViewItem;

begin

  ListView1.Clear;

  Table := DataSet1.Tables['Country'];

  { adiciona colunas do ListView conforme colunas do DataTable }

   for i := 0 to pred(Table.Columns.Count) do

   begin

    Col := Table.Columns[i];

    ListView1.Columns.Add(Col.ColumnName,100,HorizontalAlignment.Left);

   end ;

  { varra rows do DataTable }

   for i := 0 to Table.Rows.Count - 1 do

   begin

    Row := Table.Rows[i];

    lvItem := ListViewItem.Create;

    ListView1.Items.add(LvItem);

   for j := 0 to Table.Columns.Count - 1 do

    begin

      if j = 0 then

     lvItem.Text := Row[j].ToString

        else

        LvItem.SubItems.Add(Row[j].ToString);

    end;

   end ;

ComboBox1.Items.Clear;

for i := 0 to Table.Rows.Count - 1 do

   ComboBox1.Items.Add(i.ToString);

end ;

 

No código anterior varremos os Rows (objetos DataRow ) do DataTable que armazena as informações da tabela Country . Para cara Row percorremos o array Columns (de objetos DataColumn ), recuperando o valor de cada campo. Esses valores são exibidos no ListView . Observe que a “navegação” nos registros do DataTable é feito com um for , pois como comentei, o DataTable é semelhante a uma matriz.

O resultado do código pode ser visto na figura a seguir:

 

 

Adicionando, Alterando e Removendo DataRows

O código a seguir deve ser incluído no manipulador do evento Click do botão Adicionar . Ele se encarrega de criar um DataRow (chamando o método NewRow do DataTable ), configurar os valores dos campos (conforme o usuário digitou nos TextBoxes ) e incluí-lo no DataTable (método Add ).

 

procedure TWinForm.Button3_Click(sender: System.Object; e: System.EventArgs);

var

  Table: DataTable;

  Row: DataRow;

  i: integer;

begin

  Table := DataSet1.Tables['Country'];

  Row := Table.NewRow;

  Row[0] := TextBox1.Text;

  Row[1] := TextBox2.Text;

  Table.Rows.Add(Row);

  { varre novamente }

  Button1_Click( nil , nil );

end;

 

A figura abaixo mostra um registro ( DataRow ) adicionado no DataTable:

 

 

O código a seguir deve ser incluído no manipulador do evento Click do botão Alterar Ele se encarrega de alterar os valores dos campos do DataRow . Escolha o índice do registro a ser alterado no ComboBox:

 

procedure TWinForm.Button2_Click(sender: System.Object; e: System.EventArgs);

var

  Table: DataTable;

  Row: DataRow;

  i: integer;

begin

  Table := DataSet1.Tables['Country'];

   i := Convert.ToInt32(ComboBox1.Text);

   Row := Table.Rows[i];

   Row[0] := TextBox1.Text; // o mesmo que Row['Country']

   Row[1] := TextBox2.Text; // o mesmo que Row['Currency']

   Button1_Click( nil , nil );

end;

 

A figura a seguir mostra uma alteração no 4° DataRow:

 

 

O código a seguir deve ser incluído no manipulador do evento Click do botão Remover . Ele se encarrega de excluir um DataRow do DataTable (escolha no ComboBox o índice do DataRow a ser excluído):

 

procedure TWinForm.Button4_Click(sender: System.Object; e: System.EventArgs);

var

  Table: DataTable;

  Row: DataRow;

  i: integer;

begin

  Table := DataSet1.Tables['Country'];

   i := Convert.ToInt32(ComboBox1.Text);

  Table.Rows.RemoveAt(i);

  { varre novamente }

  Button1_Click( nil , nil );

end;

 

Podemos também examinar o “estado” atual de um DataRow (se o mesmo foi incluído, alterado, excluído etc.). Isso é feito no manipulador do evento Click do botão RowState , que cria uma coluna no ListView exibindo o estado do registro:

 

procedure TWinForm.Button5_Click(sender: System.Object; e:  System.EventArgs);

var

  Table: DataTable;

  Row: DataRow;

  i: integer;

  lvItem: ListViewItem;

  st: string ;

begin

  Button1_Click( nil , nil );

  ListView1.Columns.Add('RowState',100,HorizontalAlignment.Left);

  Table := DataSet1.Tables[0];

   for i := 0 to pred(Table.Rows.Count) do

 begin

   Row := Table.Rows[i];

   st := Enum.GetName(TypeOf(DataRowState),Row.RowState);

   ListView1.Items[i].SubItems.Add(st);

 end ;

end ;

 

A figura a seguir mostra o resultado da execução do código (observe a 3ª coluna do ListView):

 

 

Procurando e selecionando

O código inserido no evento Click do botão Find se encarrega de encontrar um DataRow no DataTable de acordo com o valor digitado pelo usuário no ComboBox1:

 

procedure TWinForm.Button6_Click(sender: System.Object; e: System.EventArgs);

var

 Table: DataTable;

 Row: DataRow;

 ok: array [0..0] of DataColumn;

begin

 Table := DataSet1.Tables[0];

 pk[0] := Table.Columns[0];

 Table.PrimaryKey := pk;

 Row := Table.Rows.Find(ComboBox2.Text);

 if Row <> nil then

  MessageBox.Show('Encontrou')

 else

  MessageBox.Show('Não encontrou')

end ;

 

Observe que o campo a ser localizado deve ser a chave-primária do DataTable , nesse caso estamos usando o campo Country , definido na propriedade PrimaryKey A seguir, usamos o método Find da coleção Rows do DataTable para localizar um registro. Observe que Find retorna apenas um registro.

A figura abaixo mostra uma procura pelo Country “USA”:

 

 

O código a seguir, inserido no evento Click do botão Select , se encarrega de encontrar DataRows no DataTable de acordo com a condição de busca especificada:

 

procedure TWinForm.Button7_Click(sender: System.Object; e: System.EventArgs);

var

 Table: DataTable;

 Rows: array of DataRow;

 i: integer;

 st: string ;

begin

 Table := DataSet1.Tables[0];

 Rows := Table.Select(ComboBox3.Text);

 for i := low(Rows) to high(Rows) do

 st := st + Rows[i][0].ToString + #13;

 MessageBox.Show(st);

end ;

 

A figura abaixo mostra uma procura por todos os DataRows cujo campo Country comece com “A”:

 

 

Observe que o comando LIKE (usando em consultas SQL) é aqui usado localmente, sob os dados que já estão na memória da aplicação. Não há consulta extra ao BD.

Na próxima parte do curso continuaremos estudando mais recursos do DataSet e DataTable . Até lá!

Download

Você pode fazer download de todos os exemplos deste curso de acesso a dados no Delphi 8 com ADO.NET e BDP a partir do endereço http://cc.borland.com/cc/ccweb.exe/author?authorid=222668

Leia todos artigos da série