高分求解请教个delphi三层问题:
在三层里用Clientdataset ,DBGrid ,多个Edit(用于添加多个明细)三控件,
想把多个Edit的数据暂时缓存到Clientdataset里,然后在DBGrid里显示出来,DBGrid显示一行说明添加了一条明细,显示多行说明添加了多条明细,问题出来了,DBGrid 只接受一条明细,下一次向DBGrid添加明细时,上一次添加的明细就会被本次输入的明细覆盖掉,也就是说实际只能接受一条细,为什么只能往DBGrid里输入一条明细呢?Clientdataset不可能只缓存一条记录的啊?怎么会这样?请高手支招啊....部分代码如下:
with DM_Frm.ClientDataSet4 do
  begin
DBGrid1.DataSource:=DataSource1;
  close;
commandtext:='select * from materialstable';
open;
Append;
FieldByName('原料编号').Value:=Edit6.Text;
FieldByName('原料名称').Value:=Edit17.Text;
FieldByName('规格').Value:=Edit18.Text;
FieldByName('实收数').Value:=Edit7.Text;
FieldByName('送验数').Value:=Edit15.Text;
FieldByName('件数').Value:=Edit19.Text;
FieldByName('凭单号').Value:=Edit16.Text;
FieldByName('备注').Value:=Edit20.Text;
post;
end;

解决方案 »

  1.   

    检查一下DataSource1的dataset指向哪个控件
      

  2.   

    主要是你的代码里面CLOSE了再OPEN,然而你却没ApplyUpdate.要么你增加时先执行ApplyUpdate,要么不CLOSE,最后才全部提交(执行ApplyUpdate)
      

  3.   

    依据我的经验,三层的ClientDataSet只能读操作,比较可靠,而写(更新)数据的操作,就不宜使用ClientDataSet的ApplyUpdate。
    建议在服务器中专门写一个更新数据的程序(代码),每次更新就调用它。
      

  4.   


    TO disburden
    我的DataSource1的dataset指向DM_Frm.ClientDataSet4 
      

  5.   

    TO dinoalex
    procedure TBase_Frm1.Button1Exit(Sender: TObject);
    begin
      inherited;
      DM_Frm.SocketConnection1.APPServer.BeginTran;
      Try
      DBGrid1.DataSource:=DataSource1;
      DataSource1.DataSet:=DM_Frm.ClientDataSet5;
      with DM_Frm.ClientDataSet5 do
      begin  close;
    commandtext:='select * from materialstable';
    open;
    Append;
    FieldByName('原料编号').Value:=trim(Edit1.Text);
    FieldByName('原料名称').Value:=trim(Edit2.Text);
    POST;
    //ApplyUpdates(0);
    end;
    Except
        DM_Frm.SocketConnection1.APPServer.RollBackTran;
        ShowMessage('保存失败!');
        exit;
      End;
    DM_Frm.SocketConnection1.APPServer.CommitTran;
    end;
    如上所示:我的用意是想通过post提交,在感知控件DBGrid里能显示出来,用本地Clientdataset缓存多条明细,然后通过ApplyUpdates(0)来提交在Clientdataset里的多条明细到数据库...
    这样的话,就只有Clientdataset缓存到本地,而不要用到数据库的时时表来存数据!因为考虑到两个用户同时保存明细到临时明细表的话,第一个提交明细时会看到第二个用户保存在临时明细表里的明细,如果第一个用户提交临时明细表数据到正式明细表时,会把第二个用户存在临时明细表里的数据一并提交,导致出错
      

  6.   

    回复lyhoo163
     procedure TBase_Frm1.Button1Exit(Sender: TObject);
    begin
      inherited;
      DM_Frm.SocketConnection1.APPServer.BeginTran;
      Try
      DBGrid1.DataSource:=DataSource1;
      DataSource1.DataSet:=DM_Frm.ClientDataSet5;
      with DM_Frm.ClientDataSet5 do
      begin  close;
    commandtext:='select * from materialstable';
    open;
    Append;
    FieldByName('原料编号').Value:=trim(Edit1.Text);
    FieldByName('原料名称').Value:=trim(Edit2.Text);
    POST;
    //ApplyUpdates(0);
    end;
    Except
      DM_Frm.SocketConnection1.APPServer.RollBackTran;
      ShowMessage('保存失败!');
      exit;
      End;
    DM_Frm.SocketConnection1.APPServer.CommitTran;
    end;
    如上所示:我的用意是想通过post提交,在感知控件DBGrid里能显示出来,用本地Clientdataset缓存多条明细,然后通过ApplyUpdates(0)来提交在Clientdataset里的多条明细到数据库...
    这样的话,就只有Clientdataset缓存到本地,而不要用到数据库的时时表来存数据!因为考虑到两个用户同时保存明细到临时明细表的话,第一个提交明细时会看到第二个用户保存在临时明细表里的明细,如果第一个用户提交临时明细表数据到正式明细表时,会把第二个用户存在临时明细表里的数据一并提交,导致出错
      

  7.   

    ClientDataSet指向DBGrid,可以通过SQL语句显示相关数据集,因为是三层客户端加入数据(向ClientDataSet),服务器端并未加入数据。
    不要使用ApplyUpdates(0)来提交在Clientdataset里的多条明细到数据库...,这很不可靠在。
    因此,建议你对于加入数据(行),采取二步:
    1、向ClientDataSet(即DBGrid)中加入数据行;
    2、向服务器端加入数据。
    我的代码,仅供参考:  SQL:='INSERT INTO 成品调料采购 (单位,数量,金额,ID) VALUES('+
            #39+Edit1.Text+#39+','+
            #39+ComboBox1.Text+#39+','+
            #39+ComboBox2.Text+#39+','+
            #39+ID+#39+')';
      if DataModule1.SocketConnection1.AppServer.MyQuery(sql,err)
      then begin
        DataModule1.ClientDataSet1.Append;
        DataModule1.ClientDataSet1.Fields.FieldByName('单位').AsString:=Edit1.Text;
        DataModule1.ClientDataSet1.Fields.FieldByName('数量').AsString:=ComboBox1.Text;
        DataModule1.ClientDataSet1.Fields.FieldByName('金额').AsString:=ComboBox2.Text;
        DataModule1.ClientDataSet1.Fields.FieldByName('ID').AsString:=ID;
        DataModule1.ClientDataSet1.post;
        DBGrid_AutoSize(DBGrid1,DataModule1.DataSource1);
      end
      else MessageBox(self.handle,pchar('插入数据出错:'+err),'错误',MB_OK+MB_ICONERROR);
      

  8.   

    注:
    DataModule1.SocketConnection1.AppServer.MyQuery(sql,err)
    就是调用服务器端的保存数据方法。一但远程调用成功,就在本地ClientDataSet中加入数据。使用二步的方式,非常可靠稳定。 
      

  9.   


    ClientDataSet指向DBGrid   [DBGrid1.DataSource:=DataSource1;
      DataSource1.DataSet:=DM_Frm.ClientDataSet5;]是不是这样实现?
      

  10.   

    现在的问题是,如  lyhoo163兄  所提供的步骤,第一步都没实现啊...1、向ClientDataSet(即DBGrid)中加入N数据行;
    第二步提交缓存数据到数据库倒是可以实现
    DBGrid.datasource指向datasource1,datasource1 指向 clientdataset4 ,向Clientdataset缓存多条数据,在感知控件DBGrid里能显示出来多条数据,这一想法   是不是可行?
      

  11.   

    一、你必须在服务器中,写一个上传统数据的方法。这个方法可以根据SQL语句,执行数据库文件的“插入”“更新”或“删除”.....通过DataModule1.SocketConnection1,调用服务器中的MyQuery(sql,err)方法。
    二、在客户端,分二步(1)向服务器传输数据(2)对本地的ClientDataSet,实质上就是DBGrid的数据集,相应处理。
      

  12.   

    1、向ClientDataSet(即DBGrid)中加入一行数据:(如果多行,可多次执行)  DataModule1.ClientDataSet1.Append;
      DataModule1.ClientDataSet1.Fields.FieldByName('单位').AsString:=Edit1.Text;
      DataModule1.ClientDataSet1.Fields.FieldByName('数量').AsString:=ComboBox1.Text;
      DataModule1.ClientDataSet1.Fields.FieldByName('金额').AsString:=ComboBox2.Text;
      DataModule1.ClientDataSet1.Fields.FieldByName('ID').AsString:=ID;
      DataModule1.ClientDataSet1.post;
    2、运程调用传输数据 调用服务器中的方法:MyQuery(sql,err)
    if DataModule1.SocketConnection1.AppServer.MyQuery(sql,err) then
    begin
    ...
    end;
      

  13.   

    既然是三层,本地的dbgrid是一定和本地clientdataset关联的。本地clientdataset数据操作不会直接写入到数据库的。不管是否和appserver的datasetprovider关联。如果和appserver的datasetprovider关联,可以同过clientdataset的applyupdate提交修改,否则手工传递delta到datasetprovider用其applyupdates提交数据。
      

  14.   

    楼上,所言:
    本地的dbgrid是一定和本地clientdataset关联的。本地clientdataset数据操作不会直接写入到数据库的。但写入本地是为了在DBGrid中显示数据。
      

  15.   

    正解,只向datasetprovider提交Delta就行了,lz反复open和close ClientDataSet,Delta怎么能存的住?
      

  16.   


    谢谢bluesukeke,是不应该CLOSE,否则保存不了数据到clientdataset
    谢谢所有跟贴的各位,
    谢谢lyhoo163,很热心的一位兄弟!