이 작업을 직접 수행하는 간단한 방법은 없지만 원본 및 런타임 성능의 효율성을 향상시키는 데 사용할 수있는 기술이 있습니다. 한 가지 방법은 주어진 데이터 세트에서 적절한 유형의 새 값을 초기화하는 간단한 도우미를 만드는 것입니다.
레코드 방법을 사용할 수는 있지만 캐시 된 필드 참조를 사용하면 다소 덜 우아 해 지므로 별도의 전용 초기 클래스를 제안합니다. 이것은 효율성을 위해 캐시 필드 참조를 사용할 수 있습니다
type
TPersonFDInitialiser = class
private
fldID: TIntegerField;
fldName: TStringField;
fldSurname: TStringField;
function get_NewValue: TPerson;
public
constructor Create(const aSource: TDataset);
property NewValue: TPerson read get_NewValue;
end;
이름으로 각 레코드에 대한 값을 검색 할 때마다 그들을 찾아 볼 필요 피한다 생성자에서 필드 참조를 캐싱.
constructor TPersonFDInitialiser.Create(const aSource: TDataset);
begin
inherited;
fldID := aSource.FieldByName('id') as TIntegerField;
fldName := aSource.FieldByName('name') as TStringField;
fldSurname := aSource.FieldByName('surname') as TStringField;
end;
function TPersonFDInitialiser.get_NewValue: TPerson;
begin
result.ID := fldID.Value;
result.Name := fldName.Value;
result.Surname := fldSurname.Value;
end;
당신이 볼 수 있듯이,이가 필요하다 조금 더보다 작품의 거대한 양의가 (되지 않습니다 : 필드 데이터 유형에 대한 적절한 클래스를 사용하면 어떤 변환없이 각 필드 값에 직접 액세스 할 수 있습니다
recno := 0;
init := TPersonFDInitialiser.Create(qryPersons);
try
while NOT qryPersons.EOF do
begin
persons[recno] := init.NewValue;
qryPersons.Next;
Inc(recno);
end;
finally
init.Free;
end;
qryPersons
일부 TFDQuery하는 사람 행을 반환하고 persons
이 의 배열입니다 :이 같은 작은 선물을 찾고, 한 레코드 값을 명시 적)을 초기화하지만 작성하는 반복적 인 사용을 모두 더 우아하고 신속하게 TPerson 기록 (크기/물론, 적절하게 dminesioned) (TFDQuery 궁극적으로 파생 된)을 TDataSet의 기본 클래스 당신이에서 TPerson를 초기화 할 필요가 어느 곳이 initialiser 클래스를 사용할 수를 사용하여
TDataSet의 자손, 그건 TFDQuery 또는 TClientDataset의 또는인지 어떤 (한 그 데이터 세트의 필드 기록으로, 지속적으로 명명되어 있지만, 필요한 경우 initialiser이 점에서 더 유연 할 수있다. 이것은 연습으로 남겨 둡니다.)가는
또한
사용자의 필요에 따라 이러한 initialiser 클래스의 유틸리티를 개선하기 위해 할 수있는 다양한 향상된 기능은 예를 들어, 다음과 같습니다
// To initialise a one-off, new TPerson value from a data set use a
// class function which will internally create an initialiser, obtain
// a new TPerson then destroy the initialiser for you:
//
// Note that this will need to be overloaded if it has the same name as
// the instance method (which must also then be overloaded):
class function TPersonFDInitialiser.NewValue(const aSource: TDataset): TPerson; overload;
// Implement a procedure which will initialise an existing TPerson value
// (by reference) with values from the current record.
//
// Again, a class procedure overload could be provided for one-off use
// taking care of creating and freeing the required initialiser:
class procedure TPersonFDInitialiser.SetPerson(const aSource: TDataset; var aPerson: TPerson); overload;
procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson); overload;
참고 :이 SetPerson
방법은 수 get_NewValue이 실제로 해당 메소드를 호출하여 전체 구현 중 하나의 메소드 만 구현하는 방식으로 구현됩니다. 값의 모든 설정을 수행합니다. 이렇게하면 초기화 코드가 중복되지 않으므로 initialiser 클래스의 안정성과 유지 관리가 향상됩니다.
function TPersonFDInitialiser.get_NewValue: TPerson;
begin
SetPerson(result);
end;
procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson);
begin
aPerson.ID := fldID.Value;
aPerson.Name := fldName.Value;
aPerson.Surname := fldSurname.Value;
end;
아니요, 직접 수행 할 방법이 없습니다. 레코드를 채우고 반환하는 함수를 직접 작성해야합니다. 나는 왜 그렇게 할 지 모르겠다. 데이터에 직접 액세스하거나 TClientDataSet에 저장하면 인덱스, 검색, 편집 등을 할 수 있습니다. –
RTTI는 이것을 할 수 있습니다 ... – whosrdaddy
저는 개인적으로 BLOB로 레코드를 캐시에 저장하고 있습니다 (단순히 똑같은 스트림이 TCP를 통해 들어 오기 때문입니다). – TLama