Curso de ADO.NET e BDP - Parte III

Acesso a dados no Delphi 8 for .NET

 

Parte III – BdpCommand e BdpDataReader

Nesta terceira parte do curso conheceremos o componente BdpCommand e a classe BdpDataReader do BDP.O BdpCommand permite a execução de comandos SQL ou StoredProcedures no servidor. Este componente não possui um equivalente direto nas tecnologias de acesso da VCL (dbExpress, BDE etc.).

No dbExpress, quando você usa o componente SQLQuery e acionada seu método Open , é chamado internamente um método da interface ISQLCommand e ISQLCursor para tratar a abertura da consulta. Quando você precisa executar um comando de atualização ( Insert, Update ou Delete ) diretamente, pode usar um SQLQuery e chamar seu método ExecSQL. No BDP temos um componente especializado para a execução de comandos, o BdpCommand.

Clique em File|New|Windows Forms Application e arraste até o formulário um BdpConnection e um BdpCommand. Configure a propriedade ConnectionString do BdpConnection para apontar para Employee . Aponte a propriedade Connection do BdpCommand1 para BdpConnection1.

Vamos analisa o componente BdpCommand . Sua propriedade CommandType especifica o tipo de comando, que pode ser Text , StoredProcedure ou TableDirect . Essa última opção permite que você acessar uma tabela apenas pelo Nome (ex. “EMPLOYEE”), o que é internamente transformando em um Select * from Tabela.

 

Nota: o uso de CommandText no BdpCommand é algo semelhante ao que já existia para o ClientDataSet ou SQLDataSet do dbExpress.

 

CommandText é a instrução a ser executada, ou o nome da tabela ou Stored Procedure. O método ExecuteNonQuery executa o comando, quando não retornar um resultset (ex. UPDATE,DELETE ou INSERT). Chame ExecuteReader quando o comando retornar um cursor (ex. SELECT), o retorno da função é um DataReader que pode ser utilizado para "varrer" o resultset. ExecuteScalar pode ser usado para retornar apenas o primeiro campo do primeiro registro (ideal para consultas do tipo SELECT MAX, COUNT ...). Continuando o exemplo, vamos ver como utilizar na prática essas propriedades e métodos.

Coloque no formulário dois ComboBoxes , três Buttons , um ListView , dois Labels e uma StatusBar. Seu formulário deve estar semelhante ao mostrado a seguir:

 

 

Nossa aplicação vai permitir a configuração das propriedades CommandText e CommandType em tempo de execução. Três botões fazem as chamadas aos métodos do BdpCommand , para deixar mais claro, configurei o Text de cada botão para representar o método que chamam.

No evento Load do formulário digite o seguinte:

 

procedure WinForm.WinForm_Load(sender: System.Object; e: System.EventArgs);

var

  i: integer;

  ar: &array;

begin

 BdpConnection1.Open;

 { preenhe Combo com CommandTypes usando Reflection }

 ar := Enum.GetValues(TypeOf(CommandType));

   for i := 0 to pred(ar.Length) do

    ComboBox2.Items.Add(ar.GetValue(i));

  ComboBox2.Text := ar.GetValue(0).ToString;

end;

 

 O código anterior usa reflexão para preencher o ComboBox2 com os possíveis valores para a propriedade CommandType do BdpCommand , que pode ser Text , StoredProcedure ou TableDirect:

 

 

No evento SelectedIndexChanged do ComboBox2 digite o seguinte:

 

procedure WinForm.ComboBox2_SelectedIndexChanged (

     sender: System.Object; e: System.EventArgs);

begin

  BdpCommand1.CommandType := CommandType(Enum.Parse(TypeOf(CommandType),ComboBox2.Text));

end;

 

Isso configura o CommandType de acordo com o item selecionado.  Insira o seguinte código no manipulador do evento Click do botão ExecuteNonQuery:

 

procedure WinForm.Button1_Click(sender: System.Object; e: System.EventArgs);

var

  r: integer;

begin

  ListView1.Visible := False;

  BdpCommand1.CommandText := ComboBox1.Text;

  r := BdpCommand1.ExecuteNonQuery();

  StatusBar1.Text := r.ToString + ' registros afetados';

end;

 

Aqui chamamos o método ExecuteNonQuery do BdpCommand, que retorno o número de registros afetados por um Update, Delete ou Insert (exibimos esse valor na StatusBar ).

Se o comando SQL retornar um conjunto de dados (um cursor), como em uma instrução Select , precisamos chamar o método ExecuteReader , que retorna um BdpDataReader . Utilizamos então esse objeto para varrer os registros retornados. A leitura com um BdpDataReader é forward-only e read-only , o que pode aumentar a velocidade e escalabilidade das aplicações. No entanto, não é feita a cache de dados (veremos mais sobre isso ao estudarmos o BdpDataAdapter e DataSet ). O BdpDataReader nesse caso é semelhante a um DataSet unidirecional do dbExpress, como o SQLDataSet .

A seguir, varremos o BdpDataReader e para cada registro lido informamos os valores dos campos em um ListView . Isso é feito no evento Click do botão ExecuteReader:

 

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

var

  rd: BdpDataReader;

  i: integer;

  LvItem: ListViewItem;

  r: integer;

begin

  ListView1.Clear;

  ListView1.Visible := True;

  BdpCommand1.CommandText := ComboBox1.Text;

  rd := BdpCommand1.ExecuteReader();

  { adiciona colunas do ListView conforme colunas do DataReader }

  for i := 0 to pred(rd.FieldCount) do

    ListView1.Columns.Add(rd.GetName(i),80,HorizontalAlignment.Left);

   { Percorre o DataReader - leitura sequencial ( forward - only)

      e preenche os itens do ListView }

  while rd.Read do

  begin

    lvItem := ListViewItem.Create;

    ListView1.Items.add(LvItem);

     for i := 0 to pred(rd.FieldCount) do

        if i = 0 then

         lvItem.Text := rd[rd.GetName(i)].ToString

       else

         LvItem.SubItems.Add(rd[rd.GetName(i)].ToString);

   inc(r);

  end ;

  StatusBar1.Text := r.ToString + ' registros retornados';

  rd.Close;

end ;

 

E finalmente, insira o seguinte código no manipulador do evento Click do botão ExecuteScalar:

 

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

var

  v: & object ;

begin

  ListView1.Clear;

  ListView1.Visible := True;

  BdpCommand1.CommandText := ComboBox1.Text;

  v := BdpCommand1.ExecuteScalar;

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

  ListView1.Items.Add(v.ToString);

  StatusBar1.Text := '';

end;

 ExecuteScalar pode ser utilizado para retornar apenas o primeiro campo do primeiro registro de uma consulta, o que pode aumentar a performance de consultas que usam funções como SELECT COUNT, MAX, MIN etc. Execute a aplicação e faça os testes conforme mostrado a seguir:

 

 

No próximo artigo conheceremos o BdpDataAdapter. Até lá!

Leia todos artigos da série