客户端://获取数据
var
  SQLStr1, SQLStr1:String;
  Index2Tem : String;
begin
    ....
    Index2Tem := 'StudentNo';    //建立主从表的关键字段
    SQLStr1 := 'select * from student';
    SQLStr2 := 'select * from choose';       MDForm.SQLStr1 := SQLStr1;           
    MDForm.SQLStr2 := SQLStr2;
    MDForm.CDSMaster.Active := False;                //主表学生ClientDataset
    MDForm.CDSDetail.Active := False;                 //从表选择ClientDataset      一个学生可以选择多门课程
    MDForm.CDSMaster.CommandText := SQLStr1;    
    MDForm.CDSDetail.CommandText := SQLStr2;    MDForm.CDSMaster.Execute;
    MDForm.CDSMaster.Active := True;    MDForm.CDSDetail.IndexFieldNames := Index2Tem;  
    MDForm.CDSDetail.MasterFields := Index2Tem;      //建立关联的StudentNo字段
    MDForm.CDSDetail.Execute;
    MDForm.CDSDetail.Active := True;
    .....
end;//更新数据
procedure TStandMDForm.BitBtnApplyClick(Sender: TObject);
var
  vDeltaArray    : OleVariant;
  vProviderArray : OleVariant;
  vCDSArray: array[0..1] of TClientDataset;
begin
  vCDSArray[0] := CDSMaster;
  vCDSArray[1] := CDSDetail;
  vDeltaArray    := RetrieveDeltas(vCDSArray);          //获取变化数据的数组ClientDataset.Delta
  vProviderArray := RetrieveProviders(vCDSArray);     //获取提供者的数组TDataSetProvider
  DataModule1.SCMaster.AppServer.ApplyUpdatesMD(vDeltaArray, vProviderArray, SQLStr1, SQLStr2);
  ReconcileDeltas(vCDSArray, vDeltaArray);
end;
服务器端:
//更新主从表
procedure Tco_Server.ApplyUpdatesMD(var vDeltaArray, vProviderArray: OleVariant;
  const SQLStrM, SQLStrD: WideString);
begin
  ADQMaster.Close;        //主表ADOQuery
  ADQMaster.SQL.Clear;
  ADQMaster.SQL.Add('select * from student');    //问题1  ADQDetail.Close;         //从表ADOQuery
  ADQDetail.SQL.Clear;  
  ADQDetail.SQL.Add('select * from choose');     //问题2  CDSApplyUpdates(ADOConnection1, vDeltaArray, vProviderArray, False);
  
  //真正的更新是用
  //Delta := IAppServerDisp(IDispatch(AProvider[0])).AS_ApplyUpdates(AProvider[1], Delta, 0, ErrCount, OwnerData);
  //
end;问题:当把问题1处和问题2处的SQL语句在设计时直接填入主从表Query的SQL中,更新一点问题都没有。可是当用这种运行时动态设置SQL语句的方法会出错“mismatch in datapacket”。请指教,现次感谢!

解决方案 »

  1.   

    说明:
    vCDSArray[0] := CDSMaster;    //主表ClientDataset 
    vCDSArray[1] := CDSDetail;     //从表ClientDatasetDataModule1.SCMaster.AppServer.ApplyUpdatesMD(vDeltaArray, vProviderArray, SQLStr1, SQLStr2);这句是调服务器的更新方法。
      

  2.   

    有可能是主表ADOQuery和从表ADOQuery的属性没对,因为在设计时直接将SQL语句写入主从表的SQL属性中,更新是没有问题的。
    但在更新时动态将SQL语句写入主从表ADOQuery.SQL中,就出现“mismatch in datapacket”错误。
      

  3.   

    ADOConnection1.Connected := True;
      ADOConnection1.BeginTrans;
      try
        ADQMaster.Close;
        ADQMaster.SQL.Clear;
        ADQMaster.SQL.Add(SQLStrM);
        if not VarIsNull(MasterVar) then   //主表
        begin
          MasterVar := DSPMaster.ApplyUpdates(MasterVar, 0, ErrCount);
          if ErrCount > 0 then
            SysUtils.Abort;                //这将产生回滚
        end;    ADQDetail.Close;
        ADQDetail.SQL.Clear;
        ADQDetail.SQL.Add(SQLStrD);
        if not VarIsNull(DetailVar) then   //从表
        begin
          DetailVar := DSPDetail.ApplyUpdates(DetailVar, 0, ErrCount);
          if ErrCount > 0 then
            SysUtils.Abort;                //这将产生回滚
        end;
        ADOConnection1.CommitTrans;
      except
        ADOConnection1.RollbackTrans;
      end;如果有这种,就没有问题!
      

  4.   

    看了,确实没有找到!这个例子是从《Delphi 6开发人员指南》第21章摘录下来的。讲的就是主从表的更新!
    按该书的第一种方法还可以,可是用二种方法(是对第一种方法的重构)时就不行了。
      

  5.   

    现在基本上找到原因了,如果要更新服务器里的数据,输入SQL语句的地方两次(获取数据和更新数据)应在同一地方。应该都在服务器设置SQL语言,也就是应该在:
        ADQMaster.Close;
        ADQMaster.SQL.Clear;
        ADQMaster.SQL.Add(SQLStrM);    ADQDetail.Close;
        ADQDetail.SQL.Clear;
        ADQDetail.SQL.Add(SQLStrD);
    获取数据和更新数据。
      

  6.   

    我不处理主从表问题的,在主表当前记录改变就向服务器获取细表数据,这样就不用管主从表关系了,
    cds_detail.close;
    cds_detaili.commmandText='select * from Order_Detail_Table where OrderId='''+
      cds_master.FieldByName('OrderId').AsString+'''';
    cds_detaili.open;//本人觉得这样很方便的,速度也还不错,代码一般都放在主表网格当前行改变的事件上的