Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Midas/TClientDataSet    [ Add a report in this area ]  
Report #:  2307   Status: Closed
TClientDataSet issues when stored to a file (D7)
Project:  Delphi Build #:  4.453
Version:    7.0 Submitted By:   Mark Ericksen
Report Type:  Basic functionality failure Date Reported:  9/9/2002 8:28:57 AM
Severity:    Serious / Highly visible problem Last Updated: 6/27/2006 12:27:05 PM
Platform:    95, 98, 2000, NT, XP Internal Tracking #:   146834
Resolution: Fixed (Resolution Comments) Resolved in Build: : 7.0.8.1
Duplicate of:  None
Voting and Rating
Overall Rating: (7 Total Ratings)
4.86 out of 5
Total Votes: 9
Description
The problem is that a TClientDataSet does not save data changes to a file when the FileName is set. This worked in D5 for certain. I assume D6 as well.

====================================
= Delphi 5 Implementation (working)
====================================
procedure TClientDataSet.CloseCursor;
[...]
begin
[...]
  else if FSavePacketOnClose  and (FileName <> '') then
    SaveDataPacket;
[...]
end;

====================================
= Delphi 7 Implementation (broken)
====================================
procedure TCustomClientDataSet.CloseCursor;
[...]
begin
[...]
  else if FSavePacketOnClose and (FileName = '') and (ProviderName = '') and
     (DataSetField = nil) then
    SaveDataPacket;
[...]
end;

The logic error appears to be with (FileName  = ''). I believe it *should* read (FileName <> '').
[Dave Rowntree: No, the Borland code is correct. The problem lies further up the procedure. Please see the VCL fix I supplied in the Workaround tab]
Steps to Reproduce:
Create a ClientDataset that stores data to a file.
Make changes to the data.
Close the dataset. The changes are not saved.
Workarounds
Do an explicit SaveToFile()

---------

Do an explicit SaveToFile()

---------

[Dave Rowntree:
DBCLIENT.PAS

(**) (* Delphi 6.0 - 7.0 *)
(* QC#2307 fix. *)
(* Dave Rowntree 19/Sep/03 *)
procedure TCustomClientDataSet.CloseCursor;
var
  Params: OleVariant;
  RecsOut: Integer;
  Options: TGetRecordOptions;
  ChangesMade: LongBool;
begin
  ChangesMade := True;
  if Assigned(FDSBase) then
    FDSBase.GetProp(dspropDATAHASCHANGED, @ChangesMade);

  if not (csDesigning in ComponentState) and (FileName <> '') and (*QC#2307 add this line *)
  (ChangesMade or not(FileExists(FileName))) then (*QC#2307 add this line *)
  {if (FileName <> '') and ChangesMade and not (csDesigning in ComponentState) then} (*QC#2307 rem out this line *)
  
    SaveToFile(FileName);
  inherited CloseCursor;
  if HasAppServer then
]

---------

DBCLIENT.PAS

(**) (* Delphi 6.0 - 7.0 *)
(* QC#2307 fix. *)
(* Dave Rowntree 19/Sep/03 *)
procedure TCustomClientDataSet.CloseCursor;
var
  Params: OleVariant;
  RecsOut: Integer;
  Options: TGetRecordOptions;
  ChangesMade: LongBool;
begin
  ChangesMade := True;
  if Assigned(FDSBase) then
    FDSBase.GetProp(dspropDATAHASCHANGED, @ChangesMade);

  if not (csDesigning in ComponentState) and (FileName <> '') and (*QC#2307 add this line *)
  (ChangesMade or not(FileExists(FileName))) then (*QC#2307 add this line *)
  {if (FileName <> '') and ChangesMade and not (csDesigning in ComponentState) then} (*QC#2307 rem out this line *)
  
    SaveToFile(FileName);
  inherited CloseCursor;
  if HasAppServer then
Attachment
None
Comments

Craig Stuntz at 9/9/2002 1:43:27 PM -
No, same bug is in D6, too.  This seems to have been introduced in D6.

Dave Rowntree at 9/19/2003 8:07:54 AM -
The logic being applied in D6 and D7 is that a SaveToFile will only occur when closing a CDS if data changes have been made and CDS.FileName is set.

This concept should work fine once the local file has been created, i.e., the file will only be re-saved if data changes have been made. The problem is that the file is not created unless changes are made. The fix I put in Workarounds forces a SaveToFile on CDS.Close if the CDS.FileName does not exist, which should cure the problem.

Server Response from: CODE1