很多人都说TDataSetProvider默认是无状态对象,李维在其“多层系统应用”一书中也反复强调这一观点。意思是说只要设置TClientDataSet.FetchOnDemand=false就可以使TDataSetProvider成为无状态的,不再为客户端维护Cursor。李维还在书中给出了一个复杂的算法来实现从服务器端取得下一个Pacekt数据。但真的是这样吗???为了验证这个观点,我做了如下的试验:
环境:
服务器端:一个RemoteDataModule,其中放置ADOConnetion,ADODataSet, DataSetProveder各一个,功能只是很简单从MS SQL SERVER 2000中取出一个Table的数据。
客户端:Form上放入DCOMConnectoion,DBGrid,DataSource,ClientDataSet。通过DBGrid显示服务器的数据。另外还放入一个Button,其Click Event中只有一行代码:ClientDataSet.GetNextPacket;第一次:
设置TClientDataSet的FetchOnDemand := true;PacketRecord:=10;
1.打开一个客户端,移动DBGrid的ScrollBar,一切正常,程序能自动的取得下面的数据。
2.再打开一个客户端(同一个程序),这时两个客户端都连接至同一个服务器,发现两个程序都能正常使用,说明服务器端为两个客户端独立的维护其Cursor。这与书上的说法是印证的。
第二次:
设置TClientDataSet的FetchOnDemand := false;PacketRecord:=10;
1.打开一个客户端,移动DBGrid的ScrollBar,只能看到10个记录,按下Button,取得了下一个Packet,这时可以看到共20条记录。可以看到根本不必使用李维所给出的复杂算法,只需调ClientDataSet.GetNextPacket就可以了,因此,现在我认为Provider还是维护了Cursor的。
2.再打开一个客户端(同一个程序),这时两个客户端都连接至同一个服务器,发现两个程序都能正常使用。
第三次:
这次我在客户端再加入一组(DBGrid2,DataSouce2,ClientDataSet2,Button2)组件,并且这组组件也连接至同一个Provider。其设置也与第二次时相同。
运行客户端,发现DBGrid1显示的是1-10条记录,但DBGrid2显示的是11-20条记录,按下Button1,DBGrid1中显示取得了21-30的记录,这时DBGrid1中只有20条记录,但显示的却是1-10,21-30。接着按下Button2,DBGrid2中显示出31-40的记录。试验到此,我已经可以肯定Provider不是像书上所说的无状态了。但李维的技巧在这个试验中却是很有用的。结论:可能是我还没有真正理解李维所说的无状态概念,所以我也不敢说他是错的,但至少我知道了即使将FetchOnDemand设为False,DataSetProvider还是会维护其Cursor的。而且如果你不会在一个客户端使用两个ClientDataSet连接同一个Provider,那就根本不需要编写额外的代码。最后我要说明一点,那就是从头至尾我都不相信自己是正确的(因为李维是我心目的偶像),所以才把试验过程发出来,请各位大侠指证。
环境:
服务器端:一个RemoteDataModule,其中放置ADOConnetion,ADODataSet, DataSetProveder各一个,功能只是很简单从MS SQL SERVER 2000中取出一个Table的数据。
客户端:Form上放入DCOMConnectoion,DBGrid,DataSource,ClientDataSet。通过DBGrid显示服务器的数据。另外还放入一个Button,其Click Event中只有一行代码:ClientDataSet.GetNextPacket;第一次:
设置TClientDataSet的FetchOnDemand := true;PacketRecord:=10;
1.打开一个客户端,移动DBGrid的ScrollBar,一切正常,程序能自动的取得下面的数据。
2.再打开一个客户端(同一个程序),这时两个客户端都连接至同一个服务器,发现两个程序都能正常使用,说明服务器端为两个客户端独立的维护其Cursor。这与书上的说法是印证的。
第二次:
设置TClientDataSet的FetchOnDemand := false;PacketRecord:=10;
1.打开一个客户端,移动DBGrid的ScrollBar,只能看到10个记录,按下Button,取得了下一个Packet,这时可以看到共20条记录。可以看到根本不必使用李维所给出的复杂算法,只需调ClientDataSet.GetNextPacket就可以了,因此,现在我认为Provider还是维护了Cursor的。
2.再打开一个客户端(同一个程序),这时两个客户端都连接至同一个服务器,发现两个程序都能正常使用。
第三次:
这次我在客户端再加入一组(DBGrid2,DataSouce2,ClientDataSet2,Button2)组件,并且这组组件也连接至同一个Provider。其设置也与第二次时相同。
运行客户端,发现DBGrid1显示的是1-10条记录,但DBGrid2显示的是11-20条记录,按下Button1,DBGrid1中显示取得了21-30的记录,这时DBGrid1中只有20条记录,但显示的却是1-10,21-30。接着按下Button2,DBGrid2中显示出31-40的记录。试验到此,我已经可以肯定Provider不是像书上所说的无状态了。但李维的技巧在这个试验中却是很有用的。结论:可能是我还没有真正理解李维所说的无状态概念,所以我也不敢说他是错的,但至少我知道了即使将FetchOnDemand设为False,DataSetProvider还是会维护其Cursor的。而且如果你不会在一个客户端使用两个ClientDataSet连接同一个Provider,那就根本不需要编写额外的代码。最后我要说明一点,那就是从头至尾我都不相信自己是正确的(因为李维是我心目的偶像),所以才把试验过程发出来,请各位大侠指证。
解决方案 »
- 判斷血量內存失效......
- 今年的中秋节了,祝大家团圆幸福!
- 卖掉最后几本DELPHI书。
- 为什么用表到出数据有错呢?用query1的控件怎么做呢?请教高手
- 三层架构程序中,客户端怎么连不上远程的应用服务器呢!
- 请教程序发布时数据库的问题
- 怎么点一下dbgrid中的一项,就把那一项内容,添加到listview的相对应的字段中啊?
- 能不能实现这种功能,当一个编辑控件得到焦点时,该控件就变成另一种颜色?
- 一个窗体焦点转换的问题~~
- 虚心求教:Delphi中的字符串操作函数有哪些(刚从VB转为Delphi)
- 通过ADOConnection.execute(SQL语句)后,用refresh更新记录集时提示'PK'出错。
- 请问各位大侠,如何取得ADSL的上网时间和断线时间?
在你的第三种测试方法中,你可以再试试这样:
点Button1 直到把数据全部取完,再点Button2,你会发现数据是从头开始取的。
如果交替点 Button1和 Button2 ,确实出现你所说的情况,并且在数据取完后,另一个又会从头开始取。
这种现象我认为是Midas 在客户端有问题
Tabe1.Next;
if Tabel.Eof then
Tabe1.First;
这应该就是它的处理方式吧。
其实这正好说明DataSetProvider是维护了Cursor,不然它怎么知道要取哪一段数据。
至于我说的第三个问题,其实只要再加入一个DCOMConnection就可以了,完全没有问题。我是为了做实验才这么做的。
比较成熟的做法可以用COM+,
1,将COM对象加入组件服务,
2,这个COM对象要支持IObjectControl接口 (mtx单元)
另外,如果用OOP的方法,那怎么处理更新错误?如果用RAD,可以上TClientDataSet.OnReconcileError事件中处理,但如果用OOP封装了更新操作,那如何处理?