这是一个常见但容易被忽视的问题,旧贴有问及但没答案,因此提高分数。
相信大家常这样使用Cache模式;
ADOConnection1.BeginTrans;
Try
 ADODataSet1.UpdateBatch(arAll);
 ADOConnection1.CommitTrans;
Except
 ADOConnection1.RollbackTrans;
 Raise;
End;
通常,用户会增加或修改多条记录然后保存,但是,当其中一条记录违反
数据库规则,或触发器的时候,这时会Rollback,然后提示错误,然后用户修改出错的记录,
然后再保存,这时会出现什么情况呢?(提示:除了用户刚修改的记录外,
其它记录的状态都变成了usUnmodified)同样,把这个BUG推广到多表中:
ADOConnection1.BeginTrans;
Try
 ADODataSet1.UpdateBatch(arAll);       
 ADODataSet2.UpdateBatch(arAll);       // <- 假设出错,然后用户再改正
 ADOConnection1.CommitTrans;
Except
 ADOConnection1.RollbackTrans;
 Raise;
End;同样,DataSet1的修改会被忽略。
在Borland Newsgroup上,有TeamB的高手给出了SavetoFile,LoadFromFile的
解决方案,我觉得不是一个好办法,因为LOADFROMFILE之后这个记录集的COMMANDTEXT都变成那个文件名了,
CommandType:=cmdfile了,如果SQL里面用了参数,那就很麻烦了!看看这儿大家有什么解决方法。在发贴时,我在考虑用CLONE解决这个问题!看来,BDE的两段提交(ApplyUpdate,CommitUpdate)比ADO好n倍啊,不知道BORLAND为什么要放弃他!

解决方案 »

  1.   

    ADO的bug好多呢,所以老是要升级,感觉除了连接,配置方便一点,没有什么好的
      

  2.   

    ADO是有好多问题,这是我遇到的:
    http://expert.csdn.net/Expert/topic/2081/2081914.xml?temp=.7946436
      

  3.   

    ado的bug确实很多。
    但是你的问题好像不是bug,而是delphi是否提供client端数据回滚的解决方法。
    建议看看cancelbatch方法。
      

  4.   

    几分钟前新碰到的BatchUpdate更新多个数据表join的查询数据的问题.
    假设有A、B、C三个表,B(b1,b2,b3)、C(c1,c2,c3)是基础数据表,A(a1,a2,a3,a4,a5)是业务数据表。
    有一ADOQuery:
    select a1,a2,a3,a4,a5,b2,b3,c2,c3
    from A
    join B as b on b1=a2
    join C as c on c1=a3
    where a1=a value
    录入数据后用UpdateBatch方法把数据保存到数据表中,要求只保存属于A表的字段,B、C表的字段不保存。但ADOQuery却自动地保存三个表中更新的数据,如果前台操作员在录入数据的过程中修改了基础表的数据那不是很严重的问题吗?如果用BDE的话我可以用UpdateSQL控件来控制缓存中哪些字段可以更新,虽然麻烦一点但很可靠。李维的那本《Delphi 5 ADO/MTS/COM+高级程序设计篇》说ADO采用自动更新是ADO比BDE强大,我对此不敢苟同。
    现在我正头疼怎样搞才能实现ADO只保存A表的数据呢,顺便借贴主的地方求教一下。
      

  5.   

    你用的不好,最好用Insert into or Update 语句来实现
      

  6.   

    如果用Insert into or Update语句来实现缓存数据的选择更新的话我要每条记录判断是否作出新增、修改或删除,还要自己写新增、修改、删除的SQL语句,还不如用UpdateSQL控件自动产生方便。
      

  7.   

    怎样在更新缓存记录时判定缓存中已被删除的记录?用fgPendingRecords只能过滤修改或新增的记录,用fgPredicate却是出错提示。
      

  8.   

    如果我有两个adoquery需要在同一个事务中保存,当第一个保存成功,第二个保存失败后,事务回滚,发现此时第一个adoquery的状态已经改变了,怎么恢复为保存前的状态
      

  9.   

    李维那个家伙蜻蜓点水带过,把微软的ADO吹得淋漓尽致,不知道他自己搞过开发没有
    一些很实际的问题总是避而不谈,也许可能不知道吧!!
    也觉得想听微软的讲师和专家们讲课,总说好,不说坏的!
      

  10.   

    同意THXK(THXK) 的说法,关键还是要靠自己多学习。
      

  11.   

    *****************************
    "这是一个常见但容易被忽视的问题,旧贴有问及但没答案,因此提高分数。
    相信大家常这样使用Cache模式;
    ADOConnection1.BeginTrans;
    Try
     ADODataSet1.UpdateBatch(arAll);
     ADOConnection1.CommitTrans;
    Except
     ADOConnection1.RollbackTrans;
     Raise;
    End;
    通常,用户会增加或修改多条记录然后保存,但是,当其中一条记录违反
    数据库规则,或触发器的时候,这时会Rollback,然后提示错误,然后用户修改出错的记录,
    然后再保存,这时会出现什么情况呢?(提示:除了用户刚修改的记录外,
    其它记录的状态都变成了usUnmodified)"
    *******************************
    你确定是这样吗?我试了,没有这种现象
      

  12.   

    to JetJack(喷气引擎) :
    你说的问题也一直困惑着我,这种视图更新的问题真不知道有什么好的办法来解决。我现在是用lookupfield来做,结果加了好多的lookupfield,当然这样还有问题,比如说排序就没法用一个sort属性搞定了,我刚问了这个问题,200分呢,谁会可以去捧场的说...http://expert.csdn.net/Expert/topic/2203/2203580.xml?temp=1.240176E-02
      

  13.   

    Ado的话对于每个字段均有ReadOnly属性
    针对不同的字段设置ReadOnly属性
    不允许修改的字段ReadOnly设置成True,就可以了啊
      

  14.   

    大家有空还是看看dbexpress吧,这是个不错的数据库控件,功能还是比较强大的,看看李维的《Delphi 7高效数据库程序设计》
      

  15.   

    看来,我说的你没有听明白,再说的清楚一点首先:数据库空间一般在本地有一个缓存区,在缓存区中会纪录读取时的数据,如果用户已经修改其中一条纪录的一个字段,新的数据也会写道缓存中。在向数据库进行提交会根据两个数据转换成update语句如:
    update t1 set f1 = newvalue where key1 = oldkey1 and key2 = oldkey2 and f1 = oldf1
    请注意:最后一句f1 = oldf1,这个的含义是不允许脏写。如果用户读出数据修改并保存的过程中另外一个用户修改了相同的字段,那末上面的sql更新的数据将会是0条纪录,这时候一般来说数据库控件是报错的。
    其次:数据库空间一般在缓存区中有标记,标志数据是否已经修改,如果一次更新失败后,不好的数据库空间仍然会更新缓存区的标记,因此再次更新无论如何均会出错。但是一般来说,数据库空间会提供操作缓存的函数,如ado 提供了CancelBatch等函数用于缓存的会滚,但是ado提供。此方面功能实在和专业的数据库工具pb相提并论,加上效率的问题给开发人员造成了不小的麻烦。但是看看和cCancelBatch相关的函数,处理一般的情况还是比较easy的。
    顺便说说:我用在Delphi5+ado的时候感觉bug确实很多,有ado的也有delphi的。但是在ado在2.6版本后,而对应Delphi5出了专门针对ado的补丁后,感觉bug还是不多的。但是在结果集超过5000后效率还是不好,数据读取到本地后,一个movenext要好久,恨!!!!!!!!!!!!!!!!!!!!!!