Tdatasetprovider的两个事件1:beforeapplyupdates 和2:beforeupdaterecord。当客户端调用clientdataset.applyupdates时,先触发1,再触发2。我的代码如下:

解决方案 »

  1.   

    事件1:procedure Tnewserver.scProvider1BeforeApplyUpdates(Sender: TObject;
      var OwnerData: OleVariant);
    begin
      showmessage('before apply updates');  
    end;
    事件2:procedure Tnewserver.scProvider1BeforeUpdateRecord(Sender: TObject;SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
      UpdateKind: TUpdateKind; var Applied: Boolean);
    begin
      showmessage('beforeupdatarecord');
      form1.ClientDataSet1.Data:=deltads.Delta;  //delta数据集解包
      form1.ClientDataSet1.Active:=true;
      publicsql.Close;
      publicsql.SQL.Clear;
      publicsql.SQL.Add('insert into sc(stuno,courceno,grade)'+
                         'values(:stuno,:courceno,:grade)') ;
      publicsql.Parameters[0].Value :=form1.ClientDataSet1.Fields[0].AsInteger;
      publicsql.Parameters[1].Value:=2;
      publicsql.Parameters[2].Value:=form1.ClientDataSet1.Fields[1].AsInteger;
      publicsql.ExecSQL;
    end;
    当把事件二中的showmessage('beforeupdatarecord');去掉时,两个事件按顺序执行无误,当把它加上去时后面的代码便执行不了了,而且关闭服务器时两个错误对话框:(1)未知软件异常。(2)exception EOSError in module project1.exe at 0000E132 system error.code:5.拒绝访问。
      

  2.   

    为什么 showmessageBeforeApplyUpdates 也会有相同的事发生, 因为它们是在线程中执行BeforeUpdateRecord 事件执行的次数太多你代码中问题太多, 以下也可能是异常的原因DeltaDS.Delta 不会有数据,它总是空,因为它已经是原 CDS 的 Delta
    form1 和 publicsql 是这个线程公用的变量,你没有作临界保护
      

  3.   

    to comanche(太可怕)1: “ 因为它已经是原 CDS 的 Delta” ,这句话不明白啊,麻烦你再说清楚一次。
    2:你的意思是不是两个事件是同时执行的?
    3:BeforeUpdateRecord 事件执行的次数太多 ,这会导致异常发生吗?如果是,为什么会这样?
    谢谢大师指导!
      

  4.   

    照你的程序我做了一个例子,发现没有问题,可以运行通过
    这个流程没错,可能是一些控件的属性的访问有问题吧。
    说说看把showmessage('beforeupdatarecord');加上去之后后面代码
    执行不了的详细情况
      

  5.   

    form1.ClientDataSet1.Data:=deltads.Delta;  //delta数据集解包  
    问题是这句DeltaDS.Delta 改成 DeltaDS.Data比方 ClientCDS.ApplyUpdates 后, 服务器此时 DeltaDS.Data 就是 ClientCDS.Delta, ClientCDS.Data 是没有发送回来的但这句以下代码就... 没有几句是正确的建议你在客户机上作个实验, 再放一个 ClientCDSDelta(TClientDataSet)更新(ApplyUpdates)那句改成如下 ClientCDSDelta.Data = ClientCDS.Delta放一个 DataSource 和 DBGrid 看看结果, DeltaDS 中的数据跟 ClientCDSDelta.Data 基本相同, DeltaDS 中是 ClientCDSDeltaData 中的一行记录(可能还有点差异,不是一两句可以解释)所以你之后的语句根本就不正确 
    DeltaDS 不能用 AsXXXX 取出结果(AsXXXX 读操等效于 NewValue 结果, 而写操作不允许), 而应用 NewValue, OldValue 代替...关于异常的原因很难说明
    BeforeApplyUpdates, BeforeUpdateRecord 是顺序执行, 
    ShowMessage 会阻塞线程
    Form1, publicsql 不受 Apartment 机制保护, so 临界访问很重要
      

  6.   

    form1.ClientDataSet1.Data:=deltads.Delta;  //delta数据集解包
      form1.ClientDataSet1.Active:=true;
      
      publicsql.Close;      //后来加上去的
      publicsql.SQL.Clear;
      publicsql.SQL.Add('SELECT csno FROM courses WHERE name = :courcename');
      publicsql.parameters[0].value:=courcename;
      publicsql.Open;     //到这里结束   
      
      publicsql.Close;    //从这里就不执行了
      publicsql.SQL.Clear;
      publicsql.SQL.Add('insert into sc(stuno,courceno,grade)'+
                         'values(:stuno,:courceno,:grade)') ;
      publicsql.Parameters[0].Value :=form1.ClientDataSet1.Fields[0].AsInteger;
      publicsql.Parameters[1].Value:=2;      //***改为courcename对应的课程号
      publicsql.Parameters[2].Value:=form1.ClientDataSet1.Fields[1].AsInteger;
      publicsql.ExecSQL;标记见上面,我怀疑是不是公用一个publicsql的原因?就像to comanche(太可怕)所说的“form1 和 publicsql 是这个线程公用的变量,你没有作临界保护”。可Tadoquery是线程安全的啊,不用加保护机制吧。麻烦两位再帮帮我,给点建议
      

  7.   

    试想两个人同时访问时 form1 上的 query 中是谁的语句?
      

  8.   

    form1.ClientDataSet1.Data:=deltads.Delta;  //delta数据集解包
    form1.ClientDataSet1.Active:=true;
    上面两句能正确执行,而且我在form1(form1是服务器上的窗体)上用dbgrid连到clientdataset1时能正确显示出在客户端更新的数据内容,也就是delta数据集。
    可为什么后面的那个publicsql不能执啊?