RBA
RBA

Reputation: 12584

Delphi - FieldByName.AsString - good practice

I've read an blog post(at this moment I can't find the link) where the author was saying that is faster to assign a local variable than using ADOQuery.FieldByName('...').asString or TSQLQuery.FieldByName('...').asString, when parsing an entire query with several thousands of records. I don't see the difference between

var aLocalField: TField;
....
aLocalField := ADOQuery.FieldByName('...');
..
ShowMessage(aLocalField.asString)

and by using directly

ShowMessage(ADOQuery.FieldByName('...').asString);

Blog post did not say anything about the database type or Delphi version. Is this solution related to one or another(and I'm not talking about obscure/custom database systems)?

Upvotes: 5

Views: 27062

Answers (4)

Warren  P
Warren P

Reputation: 68922

What makes sense is this:

  1. If you have a CLASS (such as a TForm) not a local function, you either persistently create the fields you avoid the cost of repeated lookup (FieldByName).

  2. If you don't use persistent fields (in a dfm), you could do a lookup once at runtime, and avoid the cost of repeatedly looking it up, if it is used either (a) more than once in the context of a single function, or (b) where it could be looked up once when the query is executed, and stored in a protected Field of an object, so that it can be reused for the life of the query or the object, as appropropriate.

Your contrived example has zero benefit, but I believe that repeated lookups of Fields when these repeated logical lookups are wasted, are perhaps a worthy thing to mention as "wasteful".

I see code like this all day, and it drives me nuts:

procedure TSomething.DoSomething;
begin
    fDataset.FieldByName('X').AsString = fDataset.FieldByName('X').AsString+'Y';
end;

The above code is made less readable by such repetitions, and such readability concerns, as well as error checking concerns are why I would avoid the above, and instead have a fX:TField field:

 TSomething = class(TBaseClass)
  protected
   fDataSet:TDataSet;
   fX:TField;

 end;

Now we can write

 fX.AsString := fX.AsString + 'Y';

I think people worry too much about Performance and not enough about quality, and long repeated subexpressions are a sign of "lack of quality" and "lack of thought" just as much as of "lack of concern for performance".

Upvotes: 5

MajidTaheri
MajidTaheri

Reputation: 3983

FieldByName use simple-search. if you want to choice more than one field. this code is better

// Same Text in StrUtils(unit)
for I:=0 to DataSet.Fields.Count-1 do 
begin
  if SameText( DataSet.Fields[I].FieldName,'Field1') then
    Field1:=DataSet.Fields[I]
  else if SameText( DataSet.Fields[I].FieldName,'Field2') then
    Field2:=DataSet.Fields[I];
end;
DataSet.First;
while not DataSet.Eof do
begin
  ProcessValue(Field.AsString);
  DataSet.Next;
end;

Upvotes: 1

user743382
user743382

Reputation:

There is no noticeable performance difference between the two. I expect what you found was the difference between

DataSet.First;
while not DataSet.Eof do
begin
  ProcessValue(DataSet.FieldByName('Field').AsString);
  DataSet.Next;
end;

versus

Field := DataSet.FieldByName('Field');
DataSet.First;
while not DataSet.Eof do
begin
  ProcessValue(Field.AsString);
  DataSet.Next;
end;

If so, the latter is more efficient because FieldByName is a (relatively) slow function. If you don't need to call it more than once, don't call it more than once.

Upvotes: 17

Related Questions