3.6 SavePoint
在DataSnap提供的功能中,有一个非常厉害特点便是当用户在客户端使用TSimpleDataSet/TClientDataSet更改数据时,DataSnap会记录每一次用户对于数据的更改。由于DataSnap会记录数据更改的过程,因此,DataSnap也允许用户把数据恢复到先前的状态。提供这个功能的就是TSimpleDataSet/TClientDataSet的SavePoint特性值。
SavePoint和数据来源提供的事务管理是不一样的,SavePoint特性值虽然可以允许程序员把数据的更改恢复成先前的状态,但这是指在客户端TSimpleDataSet/ TClientDataSet缓存内存中的记录,并不是指已经通过ApplyUpdates更新回数据来源的数据。
使用SavePoint特性值,虽然可以恢复先前对于数据的更改,但是程序员只能以往前的方式恢复数据,一旦使用了SavePoint把数据恢复成上次的状态,那么就无法以再往后的方式恢复数据。另外,当程序代码调用了ApplyUpdates方法之后,所有先前的SavePoint便失效进入重置的阶段,在随后的数据更改中SavePoint才又开始操作。
SavePoint特性值的使用非常容易,程序员只要在应用程序需要的状态下储存TSimpleDataSet/TClientDataSet的SavePoint特性值,如果在应用程序随后的阶段想要恢复数据状态时,只需把先前储存的SavePoint特性值指定回SavePoint即可。
例如下面的程序代码在TSimpleDataSet的AfterPost事件处理函数中把TSimpleDataSet的SavePoint特性值储存在一个TListBox中。而在bbtnSavePointClick事件处理函数中则是从TListBox中取出用户选择的先前储存的SavePoint数值,再指定给TSimpleDataSet的SavePoint特性值,以把数据恢复成当时阶段的状态。
procedure TForm1.sdsBooksAfterPost(DataSet: TDataSet);
begin
ListBox1.Items.Add(IntToStr(Self.sdsBooks.SavePoint));
end;
procedure TForm1. bbtnSavePointClick (Sender: TObject);
var
iSavePoint : Integer;
begin
if (ListBox1.ItemIndex <> -1) then
begin
iSavePoint := StrToInt(ListBox1.items[ListBox1.ItemIndex]);
Self.sdsBooks.SavePoint := iSavePoint;
end;
end;
procedure TForm1. bbtnApplyClick (Sender: TObject);
begin
if (Self.sdsBooks.ChangeCount > 0) then
Self.sdsBooks.ApplyUpdates(0);
end;
图3-22所示的3个画面是执行上面程序代码的结果。我们修改图3-22画面中FXXXX、FXXX1和FXXX3这3笔数据的BOOKNAME字段的数值,在每一次Post数据之后,SavePoint的数值便会被保存在TListBox中。因此,我们在下面的画面中看到了3个数值:65537、65538和65539。

图3-22 修改3笔记录并且储存了3个SavePoint数值
如果我们点击TListBox中的65538,再点击窗体中的【SavePoint】按钮,那么我们便可以看到类似图3-23所示的画面,此时TSimpleDataSet的数据已经恢复到储存第三个SavePoint之前的状态。对FXXX3这笔数据的修改也已经被恢复成未修改之前的状态了。
如果我们接着又点击TListBox中的65539,再点击【SavePoint】按钮想要再往后恢复数据的状态,那么DataSnap便会显示一个Invalid Parameter的错误对话框(见图3-24),这证明了SavePoint是只能往前恢复状态,而不能往后恢复数据状态。同样,在调用了ApplyUpdates方法把客户端所有的更改数据更新回数据来源后,所有先前的SavePoint数值也无效了。如果程序代码试着使用先前的SavePoint数值,那么也会遭遇Invalid Parameter错误对话框。

图3-23 点击第二个SavePoint数值以恢复当时的数据状态

图3-24 使用向后方式恢复SavePoint,或是在ApplyUpdates之后使用SavePoint都会造成Invalid Parameter错误






