Curso de dbExpress e DataSnap

Parte IX – InternalCalc

 

Este exemplo mostra como utilizar o recurso de InternalCalc em ClientDataSets, utilizado para otimizar campos calculados em memória. Faremos um exemplo que vai compara campos calculados tradicionais com InternalCalcs.

O evento OnCalcFields de um DataSet é uma “armadilha”. Ele é, obviamente, utilizado para implementar campos calculados. O que poucos sabem é que esse evento é chamado a todo o momento, por exemplo, quando um valor de um campo muda, mesmo que esse campo não afete o valor do cálculo. Se você escrever um código mais complexo nesse evento, como uma consulta ao banco de dados para obter um valor a ser usado no cálculo (o que considero um “suicídio”), verá que a performance da sua aplicação cairá consideravelmente.

A solução é criar o campo como InternalCalc ao invés de Calculated. A seguir, no evento OnCalcFields, testamos se o estado (State) do DataSet é dsInternalCalc antes de fazermos o processamento, como no exemplo:

 

if ClientDataSet1.State = dsInternalCalc then

  ClientDataSet1CAMPO.Value := ...

 

Com isso, o código será executado uma única vez para cada registro, por exemplo quando há uma navegação ou quando um Post é chamado.

Para ver um exemplo prático, coloque um ClientDataSet no formulário e um DataSource. Dê um duplo clique no componente e clique de direita no editor, escolhendo New Field (vamos criar um DataSet de memória neste exemplo).

Adicione o campo NUM1 como mostrado a seguir:

Archive09_1.gif 

Figura 1.

Adicione o campo NUM2 como mostrado a seguir:

Archive09_2.gif 

Figura 2.

Adicione o campo DUMMY como mostrado a seguir:

Archive09_3.gif 

Figura 3.

Adicione o campo CALCULATED como mostrado a seguir (observe que ele será um campo calculado):

Archive09_4.gif 

Figura 4.

Adicione o campo INTERNALCALC como mostrado a seguir (observe que ele será um campo InternalCalc):

Archive09_5.gif 

Figura 5.

Arraste os campos criados para o formulário, para que sejam criados os controles Data-Aware. Coloque também um DBNavigator apontando para o DataSource.

Seu formulário deve estar semelhante ao mostrado a seguir:

Archive09_6.gif 

Figura 6.

Neste exemplo, vamos processar o cálculo de NUM1 e NUM2 e atribuir a ambos os campos calculados, sem cada um é de um tipo (um internal e outro não). Para isso, no evento OnCalcFields do ClientDataSet, digitamos:

 

procedure TFrmMain.ClientDataSet1CalcFields(DataSet: TDataSet);

begin

  inherited;

  { calculado normal}

  ClientDataSet1CALCULATED.AsInteger :=

    ClientDataSet1NUM1.AsInteger +

     ClientDataSet1NUM2.AsInteger;

  {internal calc}

  if ClientDataSet1.State = dsInternalCalc then

     ClientDataSet1INTERNALCALC.AsInteger :=

      ClientDataSet1NUM1.AsInteger +

       ClientDataSet1NUM2.AsInteger;

end;

 

Execute a aplicação e digite dois valores, para NUM1 e NUM2:

Archive09_7.gif 

Figura 7.

Para ver o campo em ação, coloque dois Brekpoints no código conforme mostrado a seguir:

Archive09_8.gif 

Figura 8.

Agora digite um valor qualquer no campo DUMMY, observe que ele não afeta o cálculo, pois não serve para nada (não participa da soma). Mesmo assim, note que o código do campo calculado será executado, mesmo que a soma não seja afetada por DUMMY.

O processo não é o mesmo para o campo InternalCalc (no segundo breakpoint), ele será executado somente uma vez para fazer a soma, quando você der o Post no DataSet (mais otimizado).

Archive09_9.gif 

Figura 9.

 

Download

 

dbExpress, DataSnap e ClientDataSet: Técnicas Avançadas

Para mais informações sobre acesso a dados no Delphi e técnicas avançadas, sugiro a leitura do meu livro, “Delphi: Programação para Banco de Dados e Web”, como apoio para o aprendizado das tecnologias. Na obra mostro várias técnicas introdutórios e avançadas de desenvolvimento com ClientDataSet, dbExpress e DataSnap (multicamadas, incluindo SOAP e COM+). Para mais informações, consulte o link http://www.clubedelphi.net/guinther

 

 

 

Leia todos artigos da série