2017-03-27 2 views
1

기존 TFDMemTable에 필드를 추가 한 후 TFDLocalSQL을 통해 해당 테이블을 쿼리하는 TFDQuery가 새 필드를 인식하지 못합니다.새 필드가 TFDLocalSQL을 통해 쿼리하는 TFDMemTable에 추가 될 때 TFDQuery를 인식하는 방법

아래 코드는 코드에서 단일 필드가 추가 된 TFDMemTable과 해당 테이블에서 선택을 수행하는 TFDQuery를 보여줍니다. (TFDMemTable이 TFDLocalSQL의 DataSets 속성에 추가되고 TFDQuery가 TFDConnection을 가리키고 있다고 가정합니다.) 라이브 TFDMemTable에 필드를 추가하는 과정은 example project에서 이루어지며 Unprepare를 사용하므로이 작업이 효과가없는 것 같습니다 이 경우 question에서 온 것입니다.

procedure TForm2.FormCreate(Sender: TObject); 
begin 

    with FDMemTable1.FieldDefs.AddFieldDef do begin 
    Name := 'col1'; 
    DataType := ftString; 
    Size := 10; 
    end; 
    FDMemTable1.CreateDataSet; 
    FDMemTable1.Active := true; 

    FDQuery1.SQL.Text := 'SELECT * FROM FDMemTable1'; 

    FDConnection1.Connected := true; 
    FDLocalSQL1.Active := true; 
    FDQuery1.Active := true; 
end; 

procedure TForm2.Button1Click(Sender: TObject); 
var 
    tempMT: TFDMemTable; 
begin 
    tempMT := TFDMemTable.Create(nil); 

    try 
    tempMT.Data := FDMemTable1.Data; 
    FDMemTable1.Close; 
    with FDMemTable1.FieldDefs.AddFieldDef do begin 
     Name := 'col99'; 
     DataType := ftString; 
     Size := 10; 
    end; 
    FDMemTable1.Open; 
    FDMemTable1.MergeDataSet(tempMT, dmDataSet, mmNone); 
    if not FDMemTable1.FieldDefs.Updated then FDMemTable1.FieldDefs.Update; 
    finally 
    tempMT.Free; 

    FDQuery1.Active := false; 
    FDQuery1.Unprepare;    // this is meant to uncache the fields 
    FDQuery1.Active := true;   // Does not include 'col99' in result set 
    end; 
end; 

필드가 확실히 TFDMemTable에 추가되어 잘 작동합니다. TFDQuery에서 새 열을 인식하는 방법에 대한 정보.

답변

1

나는이 동작이 나타나는 이유가 코드에 단계가 빠져 있다고 생각합니다. 당신의 클릭 핸들러의 finally 절에서

, 당신은 위의 변화를했으면 그렇게

finally 
    tempMT.Free; 

    FDConnection1.Connected := False; 
    FDQuery1.Active := false; 
    FDQuery1.Unprepare;    // this is meant to uncache the fields 
    FDQuery1.Active := true;   // Does include 'col99' in result set 
    Caption := IntToStr(FDQuery1.FieldCount); 
    end; 
    PageControl1.ActivePage := TabSheet3; // has FDQuery grid 

처럼 FDConnection을 닫아야합니다, 당신은 당신이 FDQuery1에 추가 된 열을 얻을 것을 발견한다. Btw, 차이가 없기 때문에 FDQuery.Unprepare을 꺼낼 수 있습니다. Prepare은 일반적으로 백 엔드 DB 서버 내의 쿼리에 대한 SQL 코드를 컴파일하는 데 사용됩니다. 이 경우 FDLocalSQL1 구성 요소가 mem 테이블에서 FDQuery1에 대한 데이터를 생성하기 때문에 백엔드 서버가 관련되지 않습니다. Unprepare은 일반적으로 컴파일 된 쿼리 리소스를 릴리스 할 수 있음을 백 엔드 서버에 알립니다.

나는 버전이 작동하지 않은 이유는

function TFDCustomLocalSQL.GetActualActive: Boolean; 
begin 
    Result := Active and (Connection <> nil) and Connection.Connected; 
end; 

CheckActivate의 나머지 FDLocalSQL1 경우 건너 이렇게 정의되어 있기 때문에

procedure TFDCustomLocalSQL.CheckActivate; 
var 
    i: Integer; 
begin 
    if GetActualActive and not FActivated then begin 
    for i := 0 to DataSets.Count - 1 do 
     DataSets.CheckUnique(DataSets[i]); 
    FActivated := True; 
    InternalAttachToSQL; 
    for i := 0 to DataSets.Count - 1 do 
     if DataSets[i].IsValid then 
     InternalDataSetAdded(DataSets[i]); 
    end; 
end; 

GetActualActive에서 GetActualActive에 대한 호출의 생각 이전에 활성화되어 있었고 FDConnection이 이미 연결되어 있습니다. 따라서 FDConnection을 연결 해제하면 CheckActivate의 내부가 실행될 수 있으므로 FDLocalSQL1은 FDMemTable1의 구조에 변경 사항을 "통지"합니다.

D :

, BTW 처음부터 그 코드 그것은 오히려, 나는이 일에 내 프로젝트를 기반으로 \ D10 \ 샘플 \ FireDAC \ 샘플 \ 오브젝트 파스칼 \ 데이터베이스는 컴포지션 레이어를 \ \ TFDLocalSQL \ InMemDB

으로 프로젝트가 어떻게 설정되었는지 추측 할 필요가 없습니다.

+0

감사합니다. 그 이유는 이해하지 못했지만 효과가있었습니다. 이전에 작동하지 않는 TFDConnection을 분리했다가 다시 연결하려고했습니다. 또한 CheckActivate 소스를 다르게 읽습니다 - TFDLocalSQL은 TFDConnection이 활성화되어 있지 않은 한 활성화 할 수 없습니다. * 권장되는 활성화 순서와 맞습니다. 다시 한 번 감사드립니다. –