2016-08-26 3 views
4

델타의 TClientDataSet의 델타를 처리해야하는 코드에 문제가 있습니다. 다음 테스트 케이스로 끓였습니다.ClientDataSet의 델타 처리하기

DataSource, DBGrid 및 DBNavigator와 Delta의 Old- 및 NewValues를 표시하는 TTreeView와 함께 두 개의 ClientDataSets, cdsData 및 cdsDelta가 있습니다.

cdsDatas AfterPost에서 아래의 DisplayDelta 절차를 호출합니다.

앱을 실행하면 csdData의 한 필드 값을 변경하고 에서 'PrevValue'를 'UpdatedValue'로 변경합니다. 내 문제는 TreeView의 OldValue 및 NewValue 노드가 'UpdatedValue'를 표시하고 'PrevValue'의 흔적이 없음을 나타냅니다. 그렇다면 OldValue를 올바르게 얻으려면 어떻게해야합니까?

procedure TDeltaTestForm.DisplayDelta; 
var 
    Delta : OleVariant; 
begin 
    Delta := cdsData.Delta; 
    if not VarIsClear(Delta) then begin 
    cdsDelta.Data := Delta; 
    end; 
    if cdsData.Modified then 
    Caption := 'modified' 
    else 
    Caption := ''; 
    Caption := Caption + '/' + IntToStr(cdsData.ChangeCount); 
    BuildDeltaTree; 
end; 

procedure TDeltaTestForm.BuildDeltaTree; 
var 
    NewNode, 
    ChildNode : TTreeNode; 
    i, 
    ID : Integer; 
    Field : TField; 
    Value : String; 

    function ChildValue(ALabel : String; FieldValue : Variant) : String; 
    begin 
    Result := ALabel; 
    if VarIsClear(FieldValue) then 
     Result := Result + '(empty)' 
    else 
     if VarIsNull(FieldValue) then 
     Result := Result + '(null)' 
     else 
     Result := Result + VarToStr(FieldValue); 
    end; 
begin 
    { Find the current row in the delta dataset } 

    ID := cdsData.FieldByName('ID').AsInteger; 
    if not cdsDelta.Locate('ID', ID, []) then 
    raise Exception.CreateFmt('ID: %d not found in Delta', [ID]); 

    TreeView1.Items.BeginUpdate; 
    try 
    Treeview1.Items.Clear; 
    for i:= 0 to cdsDelta.FieldCount - 1 do begin 
     Field := cdsDelta.Fields[i]; 
     NewNode := TreeView1.Items.AddChild(Nil, Field.FieldName); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('Old: ', Field.OldValue)); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('New: ', Field.NewValue)); 
     ChildNode := TreeView1.Items.AddChild(NewNode, ChildValue('Cur: ', Field.CurValue)); 
    end; 
    TreeView1.FullExpand; 
    finally 
    TreeView1.Items.EndUpdate; 
    end; 
end; 
+0

흠. treeview의 자식 노드에 대한 코드는 RecErr.Pas (제공되는 오류 조정 형식)의 코드와 매우 유사하게 보이므로 그 이유와 작동하지 않는 이유를 즉시 알 수 없습니다. 나는 Borlander Mark Edington 전직원이 NG Post를 기억하고 있음을 모호하게 기억합니다. 나중에 ... – MartynA

+0

델타 레코드를 처리하는 방법을 알기 위해 provider.pas 및 TPacketDataSet.InitAltRecBuffers를 참조하십시오. – vavan

답변

4

문제가 재현 될 수 있습니다. 이 시도 : 이제 당신이 기다리고있어 NewValueOldValue에 대한 값을받을 수 있도록 찾아야한다

for i:= 0 to cdsDelta.FieldCount - 1 do begin 
    Field := cdsDelta.Fields[i]; 

for i:= 0 to cdsData.FieldCount - 1 do begin 
    Field := cdsData.Fields[i]; 

변경합니다. 여하튼, 나는 여기에서한다.

필자는이 점에 다소 의문점이 있습니다. 저는 항상 한 CDS의 델타를 다른 델타에 할당 할 수 있으며 두 번째 CDS는 델타와 동일한 필드 값 (Old 및 New)을 포함한다고 가정합니다. 분명히. 그러나이 결과는 Cary Jensen의 탁월한 "ClientDataSets"(6 장의 "StatusFilter vs Delta"절)에서 설명합니다.

"... CDS의 델타로 두 번째 CDS를로드하면 두 번째 CDS에는 변경 캐시가 없습니다. "

아마 그가 의미하는 바는 두 번째로 끝나는 것은 델타의 역사가 아니라 스냅 샷입니다. 나는 당신의 cdsDelta가 Field.OldValue와 Field.NewValue에서 같은 값을 반환하는 이유라고 생각합니다.

+0

델타는 원래 데이터 집합이 아닙니다. 수정 된 모든 레코드에 대해 델타 패킷에 두 개의 행이 있습니다. 첫 번째 행은 원래 필드 값을 포함하고 두 번째 행은 수정 된 값을 포함합니다 – vavan