2014-11-26 1 views
4

FDQuery 결과를 레코드 배열에 직접 복사 할 수 있습니까? 따라서이 선언 유형 :FDQuery (SQL) 결과를 Delphi 레코드 배열

type 
    TPerson = record 
    id: integer; 
    name: string; 
    surname: string; 
    end; 

type 
    TPersonList = array of TPerson; 

내가 열 id, namesurname와 SQLite는 DB가 있습니다.

var Persons: TPersonList; 
begin 
Persons[0].id := FDQuery1.FieldByName('id').AsInteger; 
.... 
.... 
.... 
end; 

을하지만,이 작업을 수행하는 더 나은/컴팩트 한 방법이 : 일반적으로이 같은 그 배열에 값을 추가해야합니까? 일부 기능은 다음과 같습니다.

while not FDQuery.eof do begin 
    ... 
    Persons[i] := FDQuery1[i]; 
    ... 
end; 

아마도 직접 또는 루프에 있습니까? 아니면 할 일을 만들어야합니까? 저는 많은 열과 다른 구조를 가진 많은 레코드 유형을 가지고 있지만 db와 같은 정확한 구조를 가지고 있습니다.

+5

아니요, 직접 수행 할 방법이 없습니다. 레코드를 채우고 반환하는 함수를 직접 작성해야합니다. 나는 왜 그렇게 할 지 모르겠다. 데이터에 직접 액세스하거나 TClientDataSet에 저장하면 인덱스, 검색, 편집 등을 할 수 있습니다. –

+0

RTTI는 이것을 할 수 있습니다 ... – whosrdaddy

+0

저는 개인적으로 BLOB로 레코드를 캐시에 저장하고 있습니다 (단순히 똑같은 스트림이 TCP를 통해 들어 오기 때문입니다). – TLama

답변

6

이 작업을 직접 수행하는 간단한 방법은 없지만 원본 및 런타임 성능의 효율성을 향상시키는 데 사용할 수있는 기술이 있습니다. 한 가지 방법은 주어진 데이터 세트에서 적절한 유형의 새 값을 초기화하는 간단한 도우미를 만드는 것입니다.

레코드 방법을 사용할 수는 있지만 캐시 된 필드 참조를 사용하면 다소 덜 우아 해 지므로 별도의 전용 초기 클래스를 제안합니다. 이것은 효율성을 위해 캐시 필드 참조를 사용할 수 있습니다

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; 
관련 문제