我有一个TClientDataSet,其中的内容是动态由多个数据集合并而来,也就是说数据源并非来自数据库或文件,现在我想记录所有对本数据的增删改,比如记住最近20个提交操作,然后当操作者觉得不行时可以提供撤销,在提交时不知道怎么获取原始数据,请各位不吝赐教。

解决方案 »

  1.   

    写一个临时表,记录CLIENTDATASET的DELTA数据集,保存40条记录就可以了,(一次修改是两条数据)。
      

  2.   

    呵呵,不晓得怎么访问delta,而且当前我并没有开启什么缓冲更新之类,实际上我这个提交是虚的,只是提交到内存里,因为数据集没有数据源,纯粹是自己写入的。
      

  3.   

    如果仅仅是Post而还没有ApplyUpdate的话,可以用CancelUpdates撤销已经Post的记录
      

  4.   

    to楼上:
       呵呵,你那方法行不通,首先我所有的数据都是缓冲进去的,一cancelupdates,我所有的工作都白干了,呵呵,再想想别的?
      

  5.   

    看看李唯的多层分布式开发好了,Clientdataset的DELTA数据集的操作
      

  6.   

    那你只能通过Delta进行还原了。就是用Delta中你要还原的记录的原字段值替换当前值就可以了
      

  7.   

    这个问题还没有解决啊,在每次POST以后就马上访问DELTA数据集,把里面的记录写进一个临时表,然后再提交,临时表里记录提交的一些情况。要撤销的时候就从临时表里面提取出来再恢复(其实就是再修改一次)。
      

  8.   

    在修改前,clone一个ClientDataset1,修改完后如果成功,就free cds1,否则,将cds1 clone回cds,
    cds1.XmlData := cds.XmlData;
    //修改
    if sucesss then
    Cds1.Free
    else
    cds.XmlData := cds1.xmlData;
      

  9.   

    建议用SavePoint来还原。在修改前存储SavePoint到数组或链表之类的。还原时只要把SavePoint设成还原点就行了。
    你的EMail是什么,我写的源码,给你发过去。
      

  10.   

    to 楼上:[email protected]
    我现在是这个用途,clientdataset的数据并没有保存的必要,因为它里面的数据是临时生成的,没有数据源,甚至连里面的字段都是随机生成的,数据集创建好后,我调用MergeChangeLog,这样就提交了所有修改,以后做任何事情,假如我想全部回滚掉,呵呵,调用CancelUpdates就可以取消全部修改,但我发现它有毛病,假如我本来排序,经这么一搞,乱了,呵呵,还好,我MergeChangelog后马上SaveToFile,要全部恢复只要load一下,就行,但还没有达到任意的,每部都可以修改,UndoLastChange的确可以每次恢复一点,但它也存在前面问题,所以要实现任意恢复,还需要讨论(比如我现在对某一列取了自然对数,实际上提交了记录条数次,但要回滚的时候却应该只要一次就能回到取对数前状态,这样UndoLastChange达不到要求)
      

  11.   

    to happy1123(飞天神鼠) :
      SavePoint在什么事件里调用呢?如果我对某列操作(比如前面说的取对数)当然可以自己调用它,但现在数据是任意可以修改的,可以这样想,操作者任意修改后提交,算一步,我自己那样应要求调整某列,虽然提交了n次,只算一步,现在的要求就是提攻类似这样的n(比如32步)步撤销
      

  12.   

    如果想实现无论提交多少次都只要一步就恢复到原始状态的话,我这里有一个方法,你可以参考。
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: integer;
    begin
      if (ClientDataSet1.UpdateStatus = usMOdified) then begin
        ClientDataSet1.Edit;
        for i := 0 to ClientDataSet1.Fields.Count - 1 do
          ClientDataSet1.FieldByName(ClientDataSet1.Fields.Fields[i].FieldName).Value
            := ClientDataSet1.Fields.Fields[i].OldValue;
        ClientDataSet1.Post;
      end;
    end;
      

  13.   

    上面的源码是这样的:你选中你要还原的记录。然后点击Button1,就可以还原到最初的状态,前提是你没有ApplyUpdate。
    至于用SavePoint,则是对整个表的,它可以分步还原,即你对同一条记录修改过n次,你可以只还原到上一次的状态,而无需一次还原到原始状态。它的前提也是你没有ApplyUpdate。
      

  14.   

    楼上,他的意思是说数据只在本地操作,没有ApplyUpdate。或者只使用临时生产的内存表
      

  15.   

    呵呵,这么热烈,好,我的数据临时生成,由n个数据集进行合并,合并成一个数据集后用于进行统计分析作图,每个数据字段都是一个序列,操作者比如觉得这列数据太大,可以取对数,或者做别的处理,比如增删改,总而言之,我的这个数据集随意操作,没有数据源,但就是要提供逐步回退,另外也不象dyzg说的回发生多个终端操作的情况,数据说白了只存在于该clientdataset的内存空间里,绝对不用applyupdate
      

  16.   

    而且只提供两种类型恢复,一是有限步数,二是完全恢复(这个savetofile后再load),不过现在有新需求,对某一序列做取对数类似操作后结果可能要在右边生成新的序列,我试了一下,发现动态增加字段比较麻烦,呵呵,大家再探讨一下。我已经做了一个数据集合并的东西,可以把n个类似数据集合并成一个,另外,也支持再往里追加数据集,基于这个,我也可以把新序列当成新数据集再追加进去,这样效率就不高,不知道有没有更好的办法。
      

  17.   

    楼主,你的一石激起千层浪了,我也认为用 SavePoint 比较适用于你的情况。
      

  18.   

    你不是临时内存表吗?那就不用那么费事了,直接在你的DataSet上增加一个临时字段就行了