Making a Locate of a ClientDataSet is very costly?

2

To make a locate of a dataset connected to the bank, it is certainly quite costly. But is it a good practice to make a locate in a dataset with data only in memory ? Or would it be better to create a array ?

Thank you.

    
asked by anonymous 30.09.2016 / 18:33

2 answers

2

Here is a simple example of using the Dictionary.

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  System.Generics.Collections, Vcl.StdCtrls;

type

  TPessoa = class
    id: integer;
    nome: string;
    sobrenome: string;
    idade: integer;
    sexo: string;
  end;

  TListaPessoa = TObjectList<TPessoa>;

  TForm2 = class(TForm)
    btnBuscarPessoa: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnBuscarPessoaClick(Sender: TObject);

  private
    FListaPessoa: TListaPessoa;
    FDicionarioPessoa: TDictionary<integer, TPessoa>;

    procedure AdicionarPessoas;
    procedure AlimentarDicionario;

  end;

var
  Form2: TForm2;

implementation

uses
  StrUtils;

{$R *.dfm}




procedure TForm2.AdicionarPessoas;
var
  i: integer;
begin

  for i := 1 to 10000 do
  begin

    FListaPessoa.Add(TPessoa.Create);
    FListaPessoa.Last.id        := i;
    FListaPessoa.Last.nome      := 'Nome' + IntToStr(Random(1000));
    FListaPessoa.Last.sobrenome := 'Sobrenome' + IntToStr(Random(1000));
    FListaPessoa.Last.idade     := Random(80);
    FListaPessoa.Last.sexo      := IfThen(odd(FListaPessoa.Last.id + FListaPessoa.Last.idade), 'M', 'F');

  end;

end;



procedure TForm2.AlimentarDicionario;
var
  FPessoa: TPessoa;
begin
  for FPessoa in FListaPessoa do
    if (not(FDicionarioPessoa.ContainsKey(FPessoa.id))) then
      FDicionarioPessoa.Add(FPessoa.id, FPessoa);
end;



procedure TForm2.FormCreate(
  Sender:
  TObject);
begin
  FListaPessoa      := TListaPessoa.Create;
  FDicionarioPessoa := TDictionary<integer, TPessoa>.Create;

  AdicionarPessoas;
  AlimentarDicionario;

end;



procedure TForm2.btnBuscarPessoaClick(Sender: TObject);
var
  identificador: integer;
begin

  identificador := Random(10000);

  ShowMessage(
    'A pessoca com o id ' + IntToStr(identificador) + ' é ' + FDicionarioPessoa.Items[identificador].nome + ' ' + FDicionarioPessoa.Items[identificador].sobrenome +
    ' tem ' + IntToStr(FDicionarioPessoa.Items[identificador].idade) + ' anos de idade e é do sexo ' +
    IfThen(FDicionarioPessoa.Items[identificador].sexo = 'M', 'masculino', 'feminino')

    );

end;

end.

Note that the legal methods of the Dictionary are ContainsKey or ContainsValue .

Note: In the test I did, I put 7000000 records, and the search is instantaneous.

Note: Data ordering is also quick with Data Dictionary.

    
03.10.2016 / 15:38
1

It is more costly in processing. Mainly because with each new run of locate, you would have to position the record at the beginning of the DataSet.

A better option would be to use FindKey ([]).

To use it, you only need to set up and use an index in the DataSet and use the fields in FindKey.

Ex:

cdsDataSet.IndexDefs.add('IDX_NOME','CAMPO1;CAMPO2;CAMPO3',[]);
cdsDataSet.IndexName := 'IDX_NOME';

// Observe que você não precisa passar todos os campos do índice
// Mas precisa seguir sempre a mesma ordem.

if cdsDataSet.FindKey([_valorCampo1, _valorCampo2]) then
  showMessage('Achei')
else
  ShowMessage('não achei');
    
16.06.2017 / 00:06