Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TClientDataset file saving

507 views
Skip to first unread message

Ron H

unread,
Jul 23, 2005, 12:21:08 AM7/23/05
to
I am using Delphi 6 Enterprise and have a question about the filesave
functionality of the TClientDataset. I went through Cary Jensen's excellent
article about using ClientDatasets
(http://bdn.borland.com/article/0,1410,29825,00.html). In watching the file
system during various points in the process, it seems that TClientDataset is
very erratic about automatically writing to TClientDataset.Filename when the
dataset is closed after the initial creation of the file. Obviously, using
the SaveToFile method gets it done, but I'm wondering if there are any
situations where the file is automatically re-written without a call to
SaveToFile?

Regards,
Ron


Bill Todd

unread,
Jul 23, 2005, 9:29:29 AM7/23/05
to
The file is never written unless you call SaveToFile.

--
Bill Todd (TeamB)

Ron H

unread,
Jul 23, 2005, 12:28:02 PM7/23/05
to
I beg to differ. Look at Cary's example. He never calls SaveToFile and yet
the file does get written upon closing the dataset.

"Bill Todd" <n...@no.com> wrote in message
news:42e24639$1...@newsgroups.borland.com...

Kostas Terzides

unread,
Jul 23, 2005, 1:58:12 PM7/23/05
to
Take a look at qc 2307. This has been a known issue in D6-7 and has been
already resolved. Try the workaround provided by (who else?) Dave RownTree.

Bill Todd

unread,
Jul 23, 2005, 2:17:43 PM7/23/05
to
Are you setting the FileName property?

--
Bill Todd (TeamB)

Ron H

unread,
Jul 24, 2005, 10:58:29 AM7/24/05
to
Yes. If user selects File/New a Savedialog gets a new filename then
CreateDataset.

"Bill Todd" <n...@no.com> wrote in message

news:42e289c7$1...@newsgroups.borland.com...

Bill Todd

unread,
Jul 24, 2005, 11:11:37 AM7/24/05
to
IIRC ClientDataSet does save on close and load on open if the FileName
property is set. I never use the FileName property and tend to forget
about it.

--
Bill Todd (TeamB)

Ron H

unread,
Jul 24, 2005, 11:33:25 AM7/24/05
to
Thanks... that sheds some light and adds a bit of confusion.

I don't think I need the workaround if I understand this correctly. I am
trying to use CDS as a standalone file-based db.

If I have filename set and ChangesMade = True then it will auto-save when
closing. However, for ChangesMade to equal true, ChangeCount > 0? And for
the changes to be in the data baseline I need to MergeChangeLog, right? So
if I don't MergeChangeLog, even though ChangeCount is >0, the changes won't
be in the saved data?

I would like to give my users a choice when closing the dataset (either
through closing application or switching to another file) as to whether they
want to save their changes or not. So (assuming filename already set) :

procedure MyForm.CloseCurrentDataset;
BEGIN
if cds.ChangeCount > then
Case YesNoMessageBoxResult of
mrOK: begin
cds.mergechangelog;
{I need to force SavetoFile because mergechangelog
resets ChangesMade?}
cds.SaveToFile(cds.filename, dfXML);
end;
mrNo: Begin
cds.close;
{This is okay because without mergechangelog,
changes won't be saved to an existing file?}
End;
end;
END;

Follow-up question, If I re-open the file and close right away, I am getting
a file prompt (as if ChangeCount > 0)? Is the log maintained outside the
cds component?

"Kostas Terzides" <kt...@otenet.gr> wrote in message
news:42e2...@newsgroups.borland.com...

Ron H

unread,
Jul 24, 2005, 2:28:28 PM7/24/05
to
Ah, the best practice. I understand why and think I will do the same.
Thanks Bill!

"Bill Todd" <n...@no.com> wrote in message

news:42e3afa9$1...@newsgroups.borland.com...

Kostas Terzides

unread,
Jul 24, 2005, 4:39:37 PM7/24/05
to
Ron H wrote:
> Thanks... that sheds some light and adds a bit of confusion.

Yes, I understand that, but let me try to explain:

-Cds.SaveToFile saves in a cds (or XML) file all the cds metadata (field
definitions e.t.c.), baseline data *and* the change log. That's the
reason you may notice a gradual increase in cds file size even though
you may only have a steady number of records. Cds.MergeChangeLog will
revert file size back to normal. The reason that change log might be
useful (in a file based app) after loading from a file is that you might
want to preserve UndoLastChange, SavePoint e.t.c.

-The check in Dave's work around (that has officialy been applied as a
fix in next versions of Delphi) is:
.....
if (FileName <> '') and not (csDesigning in ComponentState) and
(ChangesMade or not(FileExists(FileName))) then
SaveToFile(FileName);
......

That means that ChangesMade will be taken account of only in case the
cds file does not already exist (this is the first time that it is get
saved).

-ChangesMade will remain true after calling cds.MergeChangeLog.
ChangesMade is not equivalent to ChangeCount>0

-QC 2307 is only related to behaviour related to Cds.FileName property.
Cds.SaveToFile is working as expected.

>
> I don't think I need the workaround if I understand this correctly. I am
> trying to use CDS as a standalone file-based db.

And that's what I had in mind.


>
> If I have filename set and ChangesMade = True then it will auto-save when
> closing. However, for ChangesMade to equal true, ChangeCount > 0? And for
> the changes to be in the data baseline I need to MergeChangeLog, right? So
> if I don't MergeChangeLog, even though ChangeCount is >0, the changes won't
> be in the saved data?

That is not correct. Read above.


>
> I would like to give my users a choice when closing the dataset (either
> through closing application or switching to another file) as to whether they
> want to save their changes or not. So (assuming filename already set) :
>
> procedure MyForm.CloseCurrentDataset;
> BEGIN
> if cds.ChangeCount > then
> Case YesNoMessageBoxResult of
> mrOK: begin
> cds.mergechangelog;
> {I need to force SavetoFile because mergechangelog
> resets ChangesMade?}
> cds.SaveToFile(cds.filename, dfXML);
> end;
> mrNo: Begin
> cds.close;
> {This is okay because without mergechangelog,
> changes won't be saved to an existing file?}
> End;
> end;
> END;

I would simply do that as follows (if cds.FileName is set):

procedure MyForm.CloseCurrentDataset;
BEGIN
if cds.ChangeCount > then
Case YesNoMessageBoxResult of
mrOK: begin
cds.mergechangelog;

{You don't need to force SavetoFile if
cds.FileName is set}
end;
mrNo: Begin
cds.CancelUpdates;
End;
end;
Cds.Close;// That will actually save to the file
END;


>
> Follow-up question, If I re-open the file and close right away, I am getting
> a file prompt (as if ChangeCount > 0)?

Yes, because the file contains the change log. What do you mean file promt?

Is the log maintained outside the
> cds component?
>

No, read above.

Ron H

unread,
Jul 25, 2005, 12:38:44 PM7/25/05
to
Okay, I am with you on all of this and appreciate all the help! One thing
that I still need to understand is when does ChangeCount get reset? I have
written the following that is called before closing the dataset.

function TfrmMain.OkayToClose : Boolean ;
begin
Result := True;
if cdsClient.ChangeCount > 0 then
Begin
Case MessageDlg('Do you want to save your
changes?',mtConfirmation,mbYesNoCancel,0) of
mrOk : cdsclient.MergeChangeLog;
mrNo: cdsclient.CancelUpdates;
mrCancel : Result := False;
end; {endcase}
End;
end;

So if the user says ok, the changelog is merged and then the CDS closed (so
it saves). Now if I open the CDS with either a new filename or re-open the
same file and close it right away, the user is being prompted with the
Messagebox again. So ChangeCount not reset when the cds closed?

"Kostas Terzides" <kt...@otenet.gr> wrote in message

news:42e3...@newsgroups.borland.com...

Kostas Terzides

unread,
Jul 25, 2005, 1:54:15 PM7/25/05
to
Ron H wrote:
> Okay, I am with you on all of this and appreciate all the help! One thing
> that I still need to understand is when does ChangeCount get reset? I have
> written the following that is called before closing the dataset.
>
> function TfrmMain.OkayToClose : Boolean ;
> begin
> Result := True;
> if cdsClient.ChangeCount > 0 then
> Begin
> Case MessageDlg('Do you want to save your
> changes?',mtConfirmation,mbYesNoCancel,0) of
> mrOk : cdsclient.MergeChangeLog;
> mrNo: cdsclient.CancelUpdates;
> mrCancel : Result := False;
> end; {endcase}
> End;
> end;
>
> So if the user says ok, the changelog is merged and then the CDS closed (so
> it saves). Now if I open the CDS with either a new filename or re-open the
> same file and close it right away, the user is being prompted with the
> Messagebox again. So ChangeCount not reset when the cds closed?
>

In the particular case of just:
cds.Open->MergeChangeLog->cds.Close

it is true that ChangesMade will remain false and the routine will not
call SaveToFile. If you consider this a bug, then you could post a new
QC entry (I think it is a bug, a minor one though).

What Bill said at first place is the best approach after all I think,
just use SaveToFile explicitly. May be add this cds.BeforeClose event
handler (as I usually do):

cds.SaveToFile(cds.FileName);

, or even better subclass TClientDataset and override DoBeforeClose to
achieve the same functionality.

Ron H

unread,
Jul 25, 2005, 2:46:10 PM7/25/05
to
sorry I wasn't clear.

After Mergechangelog, changecount is still >0 when I test my function, even
after cds.close. When does changecount reset to zero?

"Kostas Terzides" <kt...@otenet.gr> wrote in message

news:42e5...@newsgroups.borland.com...

Kostas Terzides

unread,
Jul 25, 2005, 3:10:32 PM7/25/05
to
Ron H wrote:
> sorry I wasn't clear.
>
> After Mergechangelog, changecount is still >0 when I test my function, even
> after cds.close. When does changecount reset to zero?
>
> "Kostas Terzides" <kt...@otenet.gr> wrote in message
> news:42e5...@newsgroups.borland.com...

ChangeCount should be 0 after MergeChangeLog and CancelUpdates. What I
suspect is (from your description):

Cds.Open->Make some changes-> Cds.Close (this saves the change log to
the file)->cds.Open (ChangeCount>0 at this point)-> Cds.MergeChangeLog
(ChangeCount=0 at this point)->Cds.Close (at *this* point there is *no*
saving)->Cds.Open (it reopens the previous file that had the change log
included)->cds.ChangeCount>0

That is the only possible explanation I can give. If you check
Cds.ChangeCount (during a debugging session) immediately after
cds.MergeChangeLog and *before* closing the cds, then ChangeCount should
be 0, or else we are having another bug here that I am not aware of

Ron H

unread,
Jul 25, 2005, 3:09:20 PM7/25/05
to
You are absolutely correct! I changed so that cds.Open (ChangeCount>0 at
this point)-> Cds.MergeChangeLog (ChangeCount=0 at this
point)->CDS.SAVETOFILE ->Cds.Close and everything works great.

Thanks SO much for your patience and help!

Regards,
Ron

Bill Todd

unread,
Jul 25, 2005, 4:10:13 PM7/25/05
to
A classic example of why I don't use the FileName property.<g>

--
Bill Todd (TeamB)

0 new messages