如何将客户端的 ClientData 的数据集批量上传到服务器客户端 
 SocketConnection1+ClientDataSet1+ADOQuery1  
服务器
  DataSetProvider1+ADOQuery1

解决方案 »

  1.   

    procedure TDataModule1.ConnectionBeforeDisconnect(Sender: TObject);
    begin
      if (ClientDataSet1.ChangeCount > 0) then 
        ClientDataSet1.ApplyUpdates(-1);//这样就提交了
      end;
    end;
      

  2.   

    传ClientDataSet1.data就行啦
    另外你是指更新还是指传递数据集?
      

  3.   

    what is "批量上传"?
    ClientDataSet1.ApplyUpdates(0) 可以把所有数据上传到数据库
      

  4.   

    同意楼上几位的方法。如果你是做三层,且用SOCKET连接的话,
    把所有的数据保存到流中,
    再把流传过去。
    然后把流中的数据放回数据集中,
    再保存就可以了啊。
      

  5.   

    我觉得你可以把一个clientdataset中的数据复制到一个TDataSet中,然后再
    TdataSet转成一个string, 传到服务器端,在服务器端再将这个 string 转回成 TDataSet.就可以做处一了. 转换都有函数可用的
      

  6.   

    函数好象是  DataSetToString
      

  7.   

    谢谢各位    我的问题是这样的, 要将客户端的数据从本地数据库读出并批量上传到服务器并追加入库    客户端是用Access  服务器是用Sql server2000 最好能给个例子
      

  8.   

    TO peiweiwei(一指残)   我所指的传递数据集
      

  9.   

    to zhoutian618(周天)如果你是做三层,且用SOCKET连接的话,
    把所有的数据保存到流中,
    再把流传过去。
    然后把流中的数据放回数据集中,为什么要这样?
    SOCKET连接也可以ClientDataSet1.ApplyUpdates(0)
      

  10.   

    TO  zhoutian618(周天) 
      能不能给个具体的例子。 谢谢
      

  11.   

    To Tiejun_Chenfang()    SOCKET连接使用ClientDataSet1.ApplyUpdates(0)
       是不是要先从服务器上先取得数据集后才可修改或者添加服务器上的记录
      

  12.   

    这样做可以码?
    前台:
      ClientDataSet1从后台的ADOQuery1取回表结构,select top 0  * from 
      本地ADOQuery1 取数据;
      做循环,将本地ADOQuery1 的数据逐个append到ClientDataSet1;
      ClientDataSet1.ApplyUpdates(0)  
      

  13.   

    clientdataset 可以自动保持本地数据文件与后台数据库的同步,
    有不同的地方提交就行了。
    adoquery1.active:=true;
    if (ClientDataSet1.ChangeCount > 0) then 
     ClientDataSet1.ApplyUpdates(-1);
      

  14.   

    楼主是否想直接将前台的ADOQuery1的数据集给后台的ADOQuery1?你可以试试ClientDataSet1的DateRequest方法和DataSetProvider1的OnDataRequest事件,
    用ADOQuery1的数据集做参数
      

  15.   

    TO : IwantFlay(我很爱她!!!!!!!!!!)    我的记录中有含有 "OLE 对象"字段(使来存放图片的) 请问这样的数据也可转成 string 吗
      

  16.   

    adoquery1.active:=true;
    if (ClientDataSet1.ChangeCount > 0) then 
     ClientDataSet1.ApplyUpdates(-1);将会把你的数据上传到应用服务器的
    或用clientdataset1.data:=dataset.data;也可以的,试试看啊,
    楼主啊:有好多的东东是自己摸索出来的,我就是这样的。
      

  17.   

    TO : Tiejun_Chenfang() 能给个例子吗
      

  18.   

    TO : pwzhu666(暴龙) 谢谢,我也在试
      

  19.   

    1。先在SQL SERVER里做个DTS包,然后程序中上传你的ACCESS数据库,最后执行DTS包就行了。
    你可以一次导入多个数据表,也可以导入整个数据库,覆盖和追加就看你自己的要求了。
    2。完全用程序做的话,你就只能是一个连ACCESS,一个连SQL SERVER,然后循环读写数据吧,最后提交就行了。呵。。别的方法俺就不晓得了。
      

  20.   

    TO Tiejun_Chenfang() 
    做三层,你的客户端还会与数据库直接打交道吗?
    不会吧,
    如果做三层,客户端还直接连接数据库,跟两层有什么区别。
    那你做三层,怎么封装业务逻辑啊!!
      

  21.   

    ClientDataSet.SaveToStream(你的流, dfXML);然后把你的流传上去,
    再用ClientDataSet.LoadFromStream(你的流)加载进来,再去保存,
    就可以了啊。
      

  22.   

    建议直接ApplyUpdates()什么叫快速开发, 烦不烦哪...
      

  23.   

    1.我觉得使用----引用-----------clientdataset 可以自动保持本地数据文件与后台数据库的同步,
    有不同的地方提交就行了。
    adoquery1.active:=true;
    if (ClientDataSet1.ChangeCount > 0) then 
     ClientDataSet1.ApplyUpdates(-1);--------引用---------
    这种办法是在一定的情况下满足要求的.这种做法:
    好处:能实时的解决问题,
    坏处:但每次更新都的会再次提交浪费资源(post时间).
    2.在使用瘦客户的情况下我使用批量添加的办法是:
      1.了解被存入数据库支持不支持批量添加.
      2.如果被存入的数据库有批量添加的接口如(sql的 exec sp_dboption 下开通的 select into/b...)
      3.了解到有开通的接口后,使用机制完成工作就行了.
        例如:你从服务端取得一定量的数据后,存在客户端的数据库,客户端批量修改了记录后,把记录(在客户端新建个数据库A的_null,select * into 数据库A的_null),使用select * into 服务器数据库B_null,
      4.但使用那个办法有个缺点就是记录定位好困难.
        提供给你一些代码做记录定位(还没有很好解决,我觉得dbexpress的数据处理机制就能解决问题,但我不太懂,希望各位能提供一些该处理机制的资料就好了.my emil [email protected])
    客户同步更新{procedure TForm1.Button6Click(Sender: TObject);
    begin
    //====把本地表更新到wet------上面去
    self.ClientDataSet_local.SaveToFile('d:\adodataset_IN.xml');
    try
    self.ClientDataSet_local.ApplyUpdates(0);
    except
    showmessage('本地更新出现问题');end;}
    客户差异更新{procedure TForm1.Button4Click(Sender: TObject);
    var autoID_Z:string;
    begin    try
    //showmessage(autoID_Z);
    self.ClientDataSet_local_null.Data:=self.ClientDataSet_local.Delta;//定位记录
    //-----------bug--------------
    //当记录是多条的时候----会有只能添加最后一条的bug!
    //改进办法是: select * from wstable where autoID='+record1 +' or autoID='+record2+' autoID='+record3+'......
    //-----------bug--------------
    autoID_Z:=self.ClientDataSet_local_null.fieldbyname('AUTOID').AsString ;//showmessage(autoID_Z);
    self.ClientDataSet_local.ApplyUpdates(0);
    self.ClientDataSet_local.Close;
    self.ClientDataSet_local.CommandText:='select * from WStable where autoID='+autoID_Z+'';
    self.ClientDataSet_local.Open;
    self.ClientDataSet_local.SaveToFile('d:\adodataset_IN.xml');
        except
    showmessage('本地更新出现问题');
        end;end;}
    服务器端{procedure Tserverform.Timer2Timer(Sender: TObject);
     var  DBat : TextFile ;
          AUTOID_Y: string;
          r_I :integer;
    begin
    //===========   time 2
      //if label7.Caption ='3' then
        // begin
          // showmessage('程序导入运行良好');
           self.DCOMConnection1.Connected:=true;
           
                  if FileExists('d:\adodataset_in.xml') then
           begin
                try
                //========查找并更新数据
           //---self.ClientDataSet_IN.LoadFromFile('d:\adodataset_in.xml');
                 self.ClientDataSet_IN_null.LoadFromFile('d:\adodataset_in.xml');
           //edit1.Text :=self.ClientDataSet_IN.FieldByName('cno').AsString;
    for R_I:= 0 to self.ClientDataSet_IN_null.RecordCount  do   //
          begin
                   AUTOID_Y:=self.ClientDataSet_IN_null.fieldbyname('AUTOID').Asstring ; //付值在AUTOID_Y
                  // showmessage(autoid_Y);
                  //-------- 定位------ ClientDataSet_IN
                 self.ClientDataSet_IN.Close;
                 self.ClientDataSet_IN.CommandText:='select * from Wstable  where AUTOID='+AUTOID_Y+'';
                 //showmessage(self.ClientDataSet_IN.CommandText);
                 self.ClientDataSet_IN.Open;             //-------- 定位------ ClientDataSet_IN
                       //--------------记录存在与否------------
                       if self.ClientDataSet_IN.RecordCount<1 then
                          self.ClientDataSet_IN.Append;
                       if self.ClientDataSet_IN.RecordCount=1 then
                          self.ClientDataSet_IN.edit;
                       if self.ClientDataSet_IN.RecordCount>1 then
                          self.ClientDataSet_IN.edit;
                       //-----------bug--------------
                        //当记录是多条的时候----会有只能添加最后一条的bug!
                        //改进办法是: select * from wstable where autoID='+record1 +' or autoID='+record2+' autoID='+record3+'......
                        //-----------bug--------------                   //--------------记录存在与否------------
                                           //---------改变记录值----------     //self.ClientDataSet_IN.fieldbyname
                      //---------改变记录值----------
                 //-------- 定位------ ClientDataSet_IN_null             //-------- 定位------ ClientDataSet_IN_null
                              self.ClientDataSet_IN.ApplyUpdates(0);
                  //-----------记录偏移动--------
                  self.ClientDataSet_IN_null.Next;
          end;
                  //-----------记录偏移动--------
                 //========查找并更新数据
                //程序自己杀掉 del %0              AssignFile(DBat, 'd:\Delme.bat');
                  Rewrite(DBat);
                  Writeln(DBat,'del d:\adodataset_in.xml');  //写入删除主程序的命令
                  Writeln(DBat,'del %0');  //删除BAT文件自身
                  CloseFile(DBat);
                  WinExec('d:\Delme.bat',SW_HIDE); //执行BAT文件            //程序自己杀掉 del %0
                //==============
                {用一个小程序删除主程序,那小程序又怎么删除自己呢?
                  我见到一种方法是切实可行的,即在程序退出前写一个BAT文件,再执行它。内容如下:
                  procedure TForm1.FormDestroy(Sender: TObject);
                  var DBat: TextFile;
                  begin
                  AssignFile(DBat, 'C:\Delme.bat');
                  Rewrite(DBat);
                  Writeln(DBat,'del '+ParamStr(0));  //写入删除主程序的命令
                  Writeln(DBat,'del %0');  //删除BAT文件自身
                  CloseFile(DBat);
                  WinExec('C:\Delme.bat',SW_HIDE); //执行BAT文件
                  end;
                这种方法很巧妙,但我怕它不具有移植性,甚至在Win NT/2000/XP下会运行不了。
                所以我还需要找一种更好的办法。  }
                //==============
                edit4.Text:=edit4.Text+'\\---  d:\adodataset_in.xml  文件已经杀掉';
                except
                showmessage('程序初夏');
                end;        end
        else
                begin
                 edit4.Text:=edit4.Text+'\\---  d:\adodataset_in.xml  文件没有发现';
                 end;
       //  end;
    //===========self.Timer2.Interval  :=strTOint(self.Edit3.Text)*1000;    //间隔时间
    //self.ProgressBar1.Position:=self.ProgressBar1.Position+strTOint(self.Edit2.Text);self.Label7.Caption :=intTostr(strToint(self.Label7.Caption)+1);
    //showmessage('time1 is begin');
    if self.ProgressBar1.Position=100 thenself.ProgressBar1.Position:=0;
    end;  // self.ProgressBar1.Position=100}
    如有更好的办法如何解决请明鉴
      

  24.   

    刚写完上面的收到信,好痛苦哦,我还是自己做服务器算了
    ----------------------------------------
    尊敬的客户:    您好!
        
        1、数据库密码已经修改为:XXXXXXXX,请您测试登陆。
    2、select into/bulkcopy该功能不允许开放,您的要求无法实现。
        您本次的问题如下:

        XXXXXXXX.tif
        
    顺祝!
    有问题欢迎和我们联系。
    中国万网需要您一如既往的支持!
    ------------------------
      

  25.   

    to zhoutian618(周天)   做三层,你的客户端还会与数据库直接打交道吗?
       不会吧, 
       如果做三层,客户端还直接连接数据库,跟两层有什么区别。
       那你做三层,怎么封装业务逻辑啊!!  我并不认为用了clientdataset就不是三层,之所以我这么用是以下原因:
        1。简单的应用直接用clientdataset 的datarequest和 applyupdate 很方便
        2。复杂的应用在中间件的tlb中写自己新的接口方法固然很面向对象,但客户端总是需要导入中间件的接口方法的头文件,中间件接口稍微有修改(我不认为有很多人能够一次性完美的写出中间件),客户端就需要重新导入。
        3。我一般用clientdataset 的datarequest和beforeapplyupdate方法传给中间件参数,参数就只是一个事先定义好的字符串常量,后台根据该字符串常量,决定该如何在后台构造sql语句或者定位相应的数据库,并利用ondatarequest的参数和返回值给前台数据。
        4。这样,前台和中间件之间就只有midas固有的几个接口,然后通过这几个固有接口的参数决定后台的ondatarequest和onapplyupdates实际做什么,甚至可能根本就不是数据库操作。后台一旦要添加新的方法,只需要定义一个常量,后台的ondatarequest修改switch
    即可。客户端不需要任何重新导入。
        网上很多人认为用了midas就不是封装严密的三层了,我对此持异议。
      

  26.   

    DCOMConnection1.AppServer.AS_ApplyUpdates(...)方法试试
    或者在BeforeApplyUpdates事件中,通过owndata := ClientDataSet1.data传递。