这是以前别人的贴子,我碰到了同样的问题:
解决问题者:
可到:
http://expert.csdn.net/Expert/topic/3050/3050003.xml?temp=.199032
http://expert.csdn.net/Expert/topic/3042/3042537.xml?temp=.0526697
领分/*查资料,发帖子总是没有找到满意的答复,一气之下,晚饭也没有吃
就抱着笔记本写这篇贴子.....今天想找一个正确的解决方法*/
一、问题的前期准备工作以及说明
1、环境:Windows Professional2000(SP3)+Delphi7+ADO2.6+MS SQL Server2000
2、操作类型:Master/Detail;创建主从数据表如下:
/*创建主表*/
   Create table tMaster(
      ncID nchar(20) PRIMARY KEY NONCLUSTERED,
      dOptDate datetime not null default GetDate(),
      cField01 char(10),
      fField02 float not null default(0),
      mField03 money not null default(0)
      nOther   char(10) null
   )
/*创建从表*/
   /*ncId,cDKeyFld 共同作为子表tDetail的主键值*/
   CREATE TABLE tDetail (
ncID nchar(10)  NOT NULL REFERENCES tMaster(ncID),
cDKeyFld char(10) NOT NULL ,
cdField02 char(10) NULL ,
cdField03 char(10) NULL 
    ) ON [PRIMARY]   
3、主从数据表的连接方式:
   创建ADOQuery名称为“ADOQryM”
      ADOQryM.SQL.Text:='select * from tMaster';
   创建ADOQuery名称为“ADOQryD”
      ADOQryD.SQL.Text:='select * from tDetail where ncID=:ncId';      
4、在ADOQryM的AfterSroll事件中写如下代码:
     with ADOQryDetail do
     begin
       Close;
       Paramters.ParamByName('ncID').Value := QryADOM.FieldByName('ncID').AsString;
       Open;
     end;
5、书写添加数据、修改数据、取消操作、保存方法       
//add new
  function AddNew:Boolean;
  begin
    ...
    ADOQryM.Append;
    ....
  end;
//edit current data
  function EditCurr:Boolean;
  begin
    ...   
    ADOQryM.Edit;
    ....
  end;
//cancel updatebatch
  procedure CancelOpt;
  begin
    ...   
    ADOQryD.UpdateBatch(arAll);
    ADOQryM.UpdateBatch(arAll);  
    ...
  end;
 //save current operation
   function Save:Boolean;
   begin
     ....
     
     ADOQryD.UpdateBatch(arAll);
     ADOQryM.UpdateBatch(arAll);
     
     ....
   end; 
6、然后创建界面、添加数据集、数据显示控件、操作button.
完成上面主从数据表的updatabatch模式下的添加、修改、保存操作。 应用Delphi中的ADODataset的批处理(LockType=ltBatchOptimistic)
进行数据操作时,总是有这样的错误提示出现:1.如果我没有在写从表之前写保存主表的话,从表只能输入一条,输第二条后第一条就不见了。为什么?但如果写从表之前就保存从表的话,那要如何取消呢?2、当此时调用CancelOpt;(CancelUpdate)方法时,出现下面的错误提示
"行句柄应用了一个已被删除的行或被标示未删除的行!"对于上面这个错误我一直很头疼,我在处理主从表的时候,因为最终保存时需要检验数据的正确性
也就是在进行操作的时候不因为输入的错误而停止输入,而是把数据的检查方在了调用updateBatch
时。

解决方案 »

  1.   

    顺便说一下:
    我查我好久的资料都没解决,我想这个问题是很精典的,我不相信大家没碰到过!!
    是不是我哪里设错了,或是Ado的Bug呢!
      

  2.   

    1. 你要在从表的beforepost里面写上:
    DataSet.FieldByName('ncID').Value := QryADOM.FieldByName('ncID').AsString;2.你要把提交包在一个事务里面3.取消的时候可以用 QryADOM.Requery;
      

  3.   

    还有,之前要修改 ADOQryD , ADOQryM 的 LockType := ltBatchOptimistic;
      

  4.   

    还有,先提交Master表,再提交Detail表,即:
    function Save:Boolean;
       begin
         ....
         ADOConnection1.BeginTrans;
         try
           ADOQryM.UpdateBatch(arAll);
           ADOQryD.UpdateBatch(arAll);
           ADOConnection1.CommitTrans ;
         excetp
           ADOConnection1.RollbackTrans ;
         end;
         ....
       end;
      

  5.   

    还是没有解决:
    如果我设了主从表关系时,从表(在DBGrid中)只能输入一条,输第二条后第一条就不见了。的问题!
      

  6.   

    你的主从表怎么设置的,不可能会有这种现象,我一直用都没有见这个问题啊
    如果你的主从关系是通过参数在Master的AfterScroll事件里面写的肯定可以的
    关键要注意在从表的beforepost里面写上:
    DataSet.FieldByName('ncID').Value := QryADOM.FieldByName('ncID').AsString;
      

  7.   

    我是直接设的,我在AfterScroll里写一下试试!
      

  8.   

    我在AfterScroll里写可以了,但取消时会有错误!
    代码如下:
        if dsDetail.DataSet.State in [dsInsert,dsEdit]  then
       // dsDetail.DataSet.Cancel;
       qyDetail.CancelBatch;
      if dsMaster.DataSet.State in [dsInsert, dsEdit] then
          qyMaster.CancelUpdates;
    改成qyMaster.Requery也不行!
      

  9.   

    在AfterScroll里面写,输入是可以,但浏览上一张,下一张里就出错了!
      

  10.   

    什么:上一张,下一张???什么错误呢?procedure CancelOpt;
      begin
        ADOQryD.Requery;
        ADOQryM.Requery;
      end;
      

  11.   

    就是主表的上一笔,下一笔,首笔,末等啊
    提示:External Exception C000001d异常啊。
    yurenjf(极限) 大哥的能加我QQ吗?我用QQ问你
    QQ是:15487616
    谢谢!