我有一個主從明細表,在中間層定義了一個接口如下:
//
function TsData.AppApplyUpdate(const MasterProvider: WideString; const DetailProvider: WideString;
                            MasterData: OleVariant; DetailData: OleVariant;
                            var MasterResult: OleVariant; var DetailResult: OleVariant;const Flag: WideString='0'): WideString;
Var
  i:integer;
  sOwer:OleVariant;
  mProvider,dProvider:String;
  c : TComponent;
begin
  try
    if Flag='0' then   //開始事務
    begin
      Cn.BeginTrans
    end
    else
    begin
      AccCn.BeginTrans ;
    end;
    Result := '1';
    //主參數不能為空
    if (MasterProvider='') then Result := '參數錯語:未提供提供者對象'
    else
    begin   
      mProvider := MasterProvider;
      if VarIsEmpty(MasterData) then    //如果沒有可更新的數據則返回空
        MasterResult := null
      else        //否則提交更新
        MasterResult := AS_ApplyUpdates(mProvider,MasterData,0,i,sOwer);
      if i>0 then  //如果更新失敗則回滾
        Raise Exception.Create('1');
    end;
    if DetailProvider<>'' then    //開始明細提交
    begin
      dProvider := DetailProvider;
      if VarIsEmpty(DetailData) then       //如果無可提交數據則直接返回空
        DetailResult := null
      else            //否則應用更新
        DetailResult := AS_ApplyUpdates(DProvider,DetailData,0,i,sOwer);
      if i>0 then    //更表失敗則回滾
        Raise Exception.Create('1');
    end;
    if flag='0' then
      cn.CommitTrans
    else
      AccCn.CommitTrans ;
  except
    ON E:Exception do
    begin
      if Flag='0' then  //數據回滾
        Cn.RollbackTrans
      else
        AccCn.RollbackTrans ;
      Result := E.Message ; //返回錯誤信息
    end;
  end;
end;客戶端調用如下:procedure TfrmComMaster_Detail.aSaveExecute(Sender: TObject);
var
  MasterData,DetailData:OleVariant;
  str:string;
  i:integer;
begin
  screen.Cursor := crHourGlass;
  try
    try
      cdMaster.CheckBrowseMode;
      cdDetail.CheckBrowseMode;
      if cdMaster.ChangeCount>0 then
        MasterData := cdMaster.Delta
      else
        MasterData := null;
      if cdDetail.ChangeCount >0 then
        DetailData := cdDetail.Delta
      else
        DetailData := null;
      Str:= Data.Cn.AppServer.AppApplyUpdate(cdMaster.ProviderName,cdDetail.ProviderName,MasterData,DetailData,MasterData,DetailData,'0');
      if Str<>'1' then
        Raise Exception.Create(Str);
      cdMaster.Reconcile(MasterData);
    //  DetailDAta := Data.Cn.AppServer.AS_ApplyUpdates(cdDetail.ProviderName,DetailData,0,i,MasterDAta);
      cdDetail.Reconcile(DetailData);
    //  cdMaster.ApplyUpdates(0);
 //     cdDetail.ApplyUpdates(0);
    Except
      ON E:Exception do
      begin
        CanSave := true;
        if Pos('UNIQUE KEY',UpperCase(E.Message))>0 then
          Application.MessageBox('數據記錄已存在,保存失敗,請重輸!',PChar(Application.Title),MB_OK+MB_ICONERROR)
        else
          if Pos('COLUMN REFERENCE',UpperCase(E.Message))>0 then
            Application.MessageBox('記錄存在非法數據,請檢查!',PChar(Application.Title),MB_OK+MB_ICONERROR)
          else
            Application.MessageBox(PChar('數據保存時錯誤:'+#13+#10+'  '+E.Message),PChar(Application.Title),MB_OK+MB_ICONERROR);
        abort;
      end;
    end;
  finally
    screen.Cursor := crdefault;
  end;
end;問題是如果直接采用TClientDataSet的ApplyUpdate更新不會有錯,但如果用到接口更新就會出現Cannot perform this operation on a close dataset
不知何因,請各位幫忙看看!

解决方案 »

  1.   

    以上錯誤是中間層調用:MasterResult := AS_ApplyUpdates(mProvider,MasterData,0,i,sOwer);
    進彈出來的!
      

  2.   

    問題已解決,在客戶端調用時將Data.Cn.AppServer.AppApplyUpdate(cdMaster.ProviderName,cdDetail.ProviderName,MasterData,DetailData,MasterData,DetailData,'0');  
    改為
    Data.Cn.AppServer.AppApplyUpdate(cdMaster.ProviderName,cdDetail.ProviderName,cdMaster.Delta,cdMaster.Delta,MasterData,DetailData,'0');  就OK了!