Tenere aperta una connessione al database per tutto il tempo in cui l'utente lavora su un elenco non è sempre desiderabile: consuma una risorsa condivisa, e se la sessione cade si perde anche la possibilità di mostrare i dati già caricati. Una tecnica semplice consiste nell'eseguire la query una sola volta, copiare i risultati in un array di record e da quel momento lavorare solo in memoria, filtrando lato client senza più toccare il database.
Dalla query a un array di record
Rispetto a un semplice array di stringhe, un array di record tipizzati conserva tutti i campi che servono, non solo quello mostrato in un controllo visuale.
type
TRigaAnagrafica = record
ID: Integer;
Nome: string;
end;
TQueryResultRecordArray = class
private
FQuery: TADOQuery;
FRecordArray: TArray;
public
constructor Create(AConnection: TADOConnection);
destructor Destroy; override;
function ExecuteQuery(const SQL: string): Boolean;
function Filter(const Testo: string): TArray;
end;
constructor TQueryResultRecordArray.Create(AConnection: TADOConnection);
begin
FQuery := TADOQuery.Create(nil);
FQuery.Connection := AConnection;
end;
destructor TQueryResultRecordArray.Destroy;
begin
FQuery.Free;
inherited;
end;
function TQueryResultRecordArray.ExecuteQuery(const SQL: string): Boolean;
var
Riga: TRigaAnagrafica;
begin
Result := False;
SetLength(FRecordArray, 0);
FQuery.Close;
FQuery.SQL.Text := SQL;
try
FQuery.Open;
while not FQuery.Eof do
begin
Riga.ID := FQuery.FieldByName('ID').AsInteger;
Riga.Nome := FQuery.FieldByName('Nome').AsString;
FRecordArray := FRecordArray + [Riga];
FQuery.Next;
end;
Result := True;
finally
FQuery.Close; // i dati ormai vivono nell'array, la connessione non serve più
end;
end; Filtrare senza nuove query
Con i dati già in memoria, un filtro testuale diventa un semplice ciclo, senza dover riformulare l'SQL né riaprire la connessione:
function TQueryResultRecordArray.Filter(const Testo: string): TArray;
var
Riga: TRigaAnagrafica;
begin
SetLength(Result, 0);
for Riga in FRecordArray do
if ContainsText(Riga.Nome, Testo) then
Result := Result + [Riga];
end; Quando conviene, quando no
Questo approccio ha senso per elenchi di dimensione ragionevole (liste di anagrafiche, categorie, configurazioni) che l'utente consulta e filtra ripetutamente in una singola sessione operativa. Per dataset molto grandi o che cambiano di continuo, filtrare lato server resta la scelta più corretta: l'array in memoria è un compromesso, non una regola universale. La chiusura esplicita della connessione (FQuery.Close) subito dopo la copia dei dati è il dettaglio che rende evidente l'intenzione: da qui in poi si lavora solo sui dati locali.