Reputation: 1364
I have a dozens of functions that queries one table, check if it has a record on a gigantic array, updating or inserting as needed.
It looks something like this:
function UpdateTableA;
var
AFieldA,
AFieldB,
(...),
AFieldZ: TField;
begin
FSqlQuery.SQL.Text :=
'select fielda, fieldb, (...), fieldz '+
'from tablea '+
'where id in (0, 1, 5, 7, 8, (...))'
;
FClientDataset.Open; // this client is connected to FSqlQuery
AFieldA := FClientDataset.FieldByName('fielda');
AFieldB := FClientDataset.FieldByName('fieldb');
(...)
AFieldZ := FClientDataset.FieldByName('fieldz');
for Obj in GLongArray do
begin
if FClientDataset.locate('id', Obj.id, []) then
FClientDataset.Edit
else
FClientDataset.Insert;
AFieldA.AsInteger := Obj.ValueA;
AFieldB.AsInteger := Obj.ValueB;
(...)
end;
end;
Can I create a function in which I pass all the TField variables inside an array and initialize them there?
Something like this: (pseudo code)
function SetTFields(AFields: array of out TField);
begin
for I := 0 to FClientDataset.Fields.Count-1 do
AFields[I] := FClientDataset.Fields[I];
end;
and after opening FClientDataset, use it like this:
SetTFields([AFieldA, AFieldB, AFieldC, AFieldD, etc])
or this:
SetTFields([@AFieldA, @AFieldB, @AFieldC, @AFieldD, etc])
If not, is there some similar way to do it that doesn't involve copying a lot of variables?
Upvotes: 1
Views: 134
Reputation: 598011
You can use something like this:
type
PField: ^TField;
function SetTFields(AFields: array of PField);
begin
for I := 0 to FClientDataset.Fields.Count-1 do
AFields[I]^ := FClientDataset.Fields[I];
end;
function UpdateTableA;
var
AFieldA,
AFieldB,
(...),
AFieldZ: TField;
begin
FSqlQuery.SQL.Text := 'select fielda, fieldb, (...), fieldz '+
'from tablea '+
'where id in (0, 1, 5, 7, 8, (...))';
FClientDataset.Open; // this client is connected to FSqlQuery
SetTFields([@AFieldA, @AFieldB, (...), @AFieldZ]);
for Obj in GLongArray do
begin
if FClientDataset.Locate('id', Obj.id, []) then
FClientDataset.Edit
else
FClientDataset.Insert;
AFieldA.AsInteger := Obj.ValueA;
AFieldB.AsInteger := Obj.ValueB;
(...)
end;
end;
Or, you can use a dynamic array instead of individual variables, eg:
type
TFieldArray: array of TField;
function SetTFields(out AFields: TFieldArray);
begin
SetLength(AFields, FClientDataset.Fields.Count);
for I := 0 to FClientDataset.Fields.Count-1 do
AFields[I] := FClientDataset.Fields[I];
end;
function UpdateTableA;
var
AFields: TFieldArray;
begin
FSqlQuery.SQL.Text := 'select fielda, fieldb, (...), fieldz '+
'from tablea '+
'where id in (0, 1, 5, 7, 8, (...))';
FClientDataset.Open; // this client is connected to FSqlQuery
SetTFields(AFields);
for Obj in GLongArray do
begin
if FClientDataset.Locate('id', Obj.id, []) then
FClientDataset.Edit
else
FClientDataset.Insert;
AFields[0].AsInteger := Obj.ValueA;
AFields[1].AsInteger := Obj.ValueB;
(...)
end;
end;
Upvotes: 4