如何将客户端的 ClientData 的数据集批量上传到服务器客户端
SocketConnection1+ClientDataSet1+ADOQuery1
服务器
DataSetProvider1+ADOQuery1
SocketConnection1+ClientDataSet1+ADOQuery1
服务器
DataSetProvider1+ADOQuery1
解决方案 »
- 工具栏的 问題
- devexpress for delphi6完整自动安装版哪里有
- 总是弹出: 驱动器中没有磁盘,请在驱动器G中插入磁盘
- 谁能将这段C代码转成delphi的?
- 简单问题300
- 关于医疗IC卡系统的设计,欢迎大家讨论!
- 200分问题的解决方法、!!!急明天上来看
- 让combobox中的每一项对应一个id(id无规律)该如何写?
- Microsoft .NET Framework和DELPHI5的ADO的冲突问题
- 哪位兄弟用过WISE INSTALL SYSTEM? 急:3T
- 谁有《BORLAND传奇》一书的电子版或者链接,这里新华书店没有卖的!
- 深度探索DBGrid问题,想必大家都用到这个哈,来者有分!周末散分了哈~~~~~
begin
if (ClientDataSet1.ChangeCount > 0) then
ClientDataSet1.ApplyUpdates(-1);//这样就提交了
end;
end;
另外你是指更新还是指传递数据集?
ClientDataSet1.ApplyUpdates(0) 可以把所有数据上传到数据库
把所有的数据保存到流中,
再把流传过去。
然后把流中的数据放回数据集中,
再保存就可以了啊。
TdataSet转成一个string, 传到服务器端,在服务器端再将这个 string 转回成 TDataSet.就可以做处一了. 转换都有函数可用的
把所有的数据保存到流中,
再把流传过去。
然后把流中的数据放回数据集中,为什么要这样?
SOCKET连接也可以ClientDataSet1.ApplyUpdates(0)
能不能给个具体的例子。 谢谢
是不是要先从服务器上先取得数据集后才可修改或者添加服务器上的记录
前台:
ClientDataSet1从后台的ADOQuery1取回表结构,select top 0 * from
本地ADOQuery1 取数据;
做循环,将本地ADOQuery1 的数据逐个append到ClientDataSet1;
ClientDataSet1.ApplyUpdates(0)
有不同的地方提交就行了。
adoquery1.active:=true;
if (ClientDataSet1.ChangeCount > 0) then
ClientDataSet1.ApplyUpdates(-1);
用ADOQuery1的数据集做参数
if (ClientDataSet1.ChangeCount > 0) then
ClientDataSet1.ApplyUpdates(-1);将会把你的数据上传到应用服务器的
或用clientdataset1.data:=dataset.data;也可以的,试试看啊,
楼主啊:有好多的东东是自己摸索出来的,我就是这样的。
你可以一次导入多个数据表,也可以导入整个数据库,覆盖和追加就看你自己的要求了。
2。完全用程序做的话,你就只能是一个连ACCESS,一个连SQL SERVER,然后循环读写数据吧,最后提交就行了。呵。。别的方法俺就不晓得了。
做三层,你的客户端还会与数据库直接打交道吗?
不会吧,
如果做三层,客户端还直接连接数据库,跟两层有什么区别。
那你做三层,怎么封装业务逻辑啊!!
再用ClientDataSet.LoadFromStream(你的流)加载进来,再去保存,
就可以了啊。
有不同的地方提交就行了。
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}
如有更好的办法如何解决请明鉴
----------------------------------------
尊敬的客户: 您好!
1、数据库密码已经修改为:XXXXXXXX,请您测试登陆。
2、select into/bulkcopy该功能不允许开放,您的要求无法实现。
您本次的问题如下:
XXXXXXXX.tif
顺祝!
有问题欢迎和我们联系。
中国万网需要您一如既往的支持!
------------------------
不会吧,
如果做三层,客户端还直接连接数据库,跟两层有什么区别。
那你做三层,怎么封装业务逻辑啊!! 我并不认为用了clientdataset就不是三层,之所以我这么用是以下原因:
1。简单的应用直接用clientdataset 的datarequest和 applyupdate 很方便
2。复杂的应用在中间件的tlb中写自己新的接口方法固然很面向对象,但客户端总是需要导入中间件的接口方法的头文件,中间件接口稍微有修改(我不认为有很多人能够一次性完美的写出中间件),客户端就需要重新导入。
3。我一般用clientdataset 的datarequest和beforeapplyupdate方法传给中间件参数,参数就只是一个事先定义好的字符串常量,后台根据该字符串常量,决定该如何在后台构造sql语句或者定位相应的数据库,并利用ondatarequest的参数和返回值给前台数据。
4。这样,前台和中间件之间就只有midas固有的几个接口,然后通过这几个固有接口的参数决定后台的ondatarequest和onapplyupdates实际做什么,甚至可能根本就不是数据库操作。后台一旦要添加新的方法,只需要定义一个常量,后台的ondatarequest修改switch
即可。客户端不需要任何重新导入。
网上很多人认为用了midas就不是封装严密的三层了,我对此持异议。
或者在BeforeApplyUpdates事件中,通过owndata := ClientDataSet1.data传递。