问题
I have a TADODataSet connected with a stored procedure which produce 40 Columns * 800 Row the TADODataSet has an AfterOpen event which assign an OnGetText for it is Fields like :
procedure TForm1.ADODataSet1AfterOpen(DataSet: TDataSet);
begin
with DataSet do
begin
Fields[4].DisplayLabel:=TR(AS2); //RefId
Fields[4].DisplayWidth:=8;
Fields[4].Tag:=1;
Fields[4].OnGetText:=RefGetText;
Fields[5].DisplayLabel:=TR(AS3); //ClientId
Fields[5].DisplayWidth:=8;
Fields[5].Tag:=1;
Fields[5].OnGetText:=ClientGetText;
end;
end;
procedure TForm1.RefGetText(Sender: TField; var Text: String; DisplayText: Boolean);
begin
if Sender.DataSet.FieldByName('RelStoreId').AsString='' then
Text:='NO REF ID'
else
KHDM.RefGetText(Sender,Text,DisplayText);
end;
procedure TForm1.ClientGetText(Sender: TField; var Text: String; DisplayText: Boolean);
begin
if Sender.DataSet.FieldByName('ClientId').AsString='' then
Text:='Client ID is not Assigned'
else
KHDM.ClientGetText(Sender,Text,DisplayText);
end;
I want to export the data to an XML with the texts I don't want to make a loop on fields and records because it is very slow I want something like bulk copy to stream or something like that
I cannot change the way I'm working because there are around 800 module which using the same way...
please help.
回答1:
There is not much you can do to optimize this, since you don't want to make too many changes.
I hope you can optimize this: If your dataset has fixed fields (added in design time), you can reference the field using the component field, which is usually named as DataSetNameFieldName, (for instance cdsEmployeeEMPNO).
If that is the case, you can reference cdsEmployeeEMPNO.AsString
(or whatever property you need).
The reason this is faster, is because the field component you use in this case, already knows which field it refers to.
In your case, you use a lookup by name: if Sender.DataSet.FieldByName('RelStoreId').AsString=
..
This means that each and every time, the code performs DataSet.Fields.IndexOf(FieldName)
. This is a slow lookup, because those fields aren't sorted or anything. Given the size of your dataset, this can be thousands of such lookups, which can easily be twice as fast if you do it smarter.
If, for some reason, you cannot use these field component wrappers, you can also perform the lookup once, store the indexes of the fields you need in variables in your datamodule and request the value like this: if Sender.DataSet.Fields[RelStoreIdIndex].AsString=
You now use the index of the field directly, which saves the lookup. This will make it a little faster.
Note however that XML outputting is slow as well. You don't show any code of the export, but maybe there could be some serious possibilities for optimization there. It's always good to do some profiling on various parts of your code to find the actual bottleneck, before you start refactoring everything.
回答2:
I have used this kind of technique before - Any Help to you ? I can see the length of the output is a problem but you might be able to fettle it somehow. Perhaps look at the ClientDataset.SavetoFile() Method
function DataSetToXml(const ADataSet : TOraQuery) : String;
var
Provider : TDataSetProvider;
ClientDataSet : TClientDataset;
begin
Provider := TDataSetProvider.Create(nil);
try
Provider.Name := 'tmpProvider';
Provider.DataSet := ADataSet;
ClientDataSet := TClientDataSet.Create(nil);
try
ClientDataSet.Data := Provider.Data;
Result := ClientDataSet.XMLData;
finally
FreeAndNil(ClientDataSet);
end;
finally
FreeAndNil(Provider);
end;
end;
来源:https://stackoverflow.com/questions/13605901/how-to-export-tadodataset-with-fields-texts-not-fields-values