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
- Curso de ADO.NET e BDP - Parte I
- Curso de ADO.NET e BDP - Parte II
- Curso de ADO.NET e BDP - Parte III
- Curso de ADO.NET e BDP - Parte IV
- Curso de ADO.NET e BDP - Parte V
- Curso de ADO.NET e BDP - Parte VI
- Curso de ADO.NET e BDP - Parte VII
- Curso de ADO.NET e BDP - Parte IX
- Curso de ADO.NET e BDP - Parte X
- Curso de ADO.NET e BDP - Parte XI
- Curso de ADO.NET e BDP - Parte XII
- Curso de ADO.NET e BDP - Parte XIII
- Curso de ADO.NET e BDP - Parte XIV
- Curso de ADO.NET e BDP - Parte XV
- Curso de ADO.NET e BDP - Parte XVI
- Curso de ADO.NET e BDP - Parte XVII
- Curso de ADO.NET e BDP - Parte XVIII
- Curso de ADO.NET e BDP - Parte XIX
- Curso de ADO.NET e BDP - Final