質問のタイトルにあるように、計算フィールドの使用方法について同僚と議論しています。私の知る限り、実行時に計算フィールドをクエリに追加するという質問に対するフランソワの回答のように、計算フィールドは実行時に作成されます。同じ質問には、sabri.arslan からの別の回答があり、既存のフィールドを計算されたフィールドに変更することを提案しています (以下のコード)。
var
initing:boolean;
procedure TSampleForm.dsSampleAfterOpen(
DataSet: TDataSet);
var
i:integer;
dmp:tfield;
begin
if not initing then
try
initing:=true;
dataset.active:=false;
dataset.FieldDefs.Update;
for i:=0 to dataset.FieldDefs.Count-1 do
begin
dmp:=DataSet.FieldDefs.Items[i].FieldClass.Create(self);
dmp.FieldName:=DataSet.FieldDefs.Items[i].DisplayName;
dmp.DataSet:=dataset;
if (dmp.fieldname='txtState') or (dmp.FieldName='txtOldState') then
begin
dmp.Calculated:=true;
dmp.DisplayWidth:=255;
dmp.size:=255;
end;
end;
dataset.active:=true;
finally
initing:=false;
end;
end;
procedure TSampleForm.dsSampleAfterClose(
DataSet: TDataSet);
var
i:integer;
dmp:TField;
begin
if not initing then
begin
for i:=DataSet.FieldCount-1 downto 0 do
begin
dmp:=pointer(DataSet.Fields.Fields[i]);
DataSet.Fields.Fields[i].DataSet:=nil;
freeandnil(dmp);
end;
DataSet.FieldDefs.Clear;
end;
end;
procedure TSampleForm.dsSampleCalcFields(
DataSet: TDataSet);
var
tmpdurum,tmpOldDurum:integer;
begin
if not initing then
begin
tmpDurum := dataset.FieldByName( 'state' ).AsInteger;
tmpOldDurum:= dataset.FieldByName( 'oldstate' ).AsInteger;
dataset.FieldByName( 'txtState' ).AsString := State2Text(tmpDurum);
dataset.FieldByName( 'txtOldState' ).AsString := State2Text(tmpOldDurum);
end;
end;
procedure TSampleForm.btnOpenClick(Sender: TObject);
begin
if dsSample.Active then
dsSample.Close;
dsSample.SQL.text:='select id,state,oldstate,"" as txtState,"" as txtOldState from states where active=1';
dsSample.Open;
end;
この変更は、指定された TField の未知の動作につながると思います。ランタイムでデータセット フィールドを計算フィールドに変更しても安全ですか? これにより、どのような問題が発生する可能性がありますか?
LE: これは質問です。その目的は、実行時にデータセットに計算フィールドを追加するための優れた方法を示すことです。そして、はい、実行時に計算フィールドを追加するのは悪い設計です。
LE2: これは、「このようにしないでください」の単なる例です。議論として、これを行った後の議論でフィールドの動作は何かを尋ねました。そのフィールドはどのように機能しますか?