很多人都说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,那就根本不需要编写额外的代码。最后我要说明一点,那就是从头至尾我都不相信自己是正确的(因为李维是我心目的偶像),所以才把试验过程发出来,请各位大侠指证。

解决方案 »

  1.   

    DataSetProvider 应该是无状态。
    在你的第三种测试方法中,你可以再试试这样:
    点Button1 直到把数据全部取完,再点Button2,你会发现数据是从头开始取的。
    如果交替点 Button1和 Button2 ,确实出现你所说的情况,并且在数据取完后,另一个又会从头开始取。
    这种现象我认为是Midas 在客户端有问题
      

  2.   

    你说的情况当然不错,但这是因为TDataSetProvider的Cursor到数据末尾后自已移动至第一个罢了。我们都写过如下的程序:
    Tabe1.Next;
    if Tabel.Eof then
      Tabe1.First;
    这应该就是它的处理方式吧。
    其实这正好说明DataSetProvider是维护了Cursor,不然它怎么知道要取哪一段数据。
    至于我说的第三个问题,其实只要再加入一个DCOMConnection就可以了,完全没有问题。我是为了做实验才这么做的。
      

  3.   

    tclientdataset应该是 无状态模式,你也可以将去数据报放到服务器上的方法中,,而不是直接用PROVIDER来去。
      

  4.   

    我说的是TDataSetProvider,而不是ClientDataSet,他是在客户端,无所谓有没有状态.
      

  5.   

    所谓的无状态对象,是指其不为特定的客户维护状态信息,如果使用了对象缓冲的技术,在一个客户端的连接关闭后,无状态对象并不释放,可以继续保持在内存中,为下一个客户端所用。其自身的一些信息在这个过程中仍然会保持地,如数据集的指针,属性值等。在你所做的例子中,并未用到对象缓冲技术,每开启一个客户端,服务器端便建立一个RemoteDatamodule的实例,执行在不同的线程中,两个客户端使用的并非是同一个对象,两个对象互不干扰,GetNextPacket取得的数据也不会出现彼此影响的情况。
      

  6.   

    TOMWLD(仰首再笑天) ,那要怎样才能使用Object Pooling呢?
      

  7.   

    使用OBJECT POOLING可以自己编程,象DELPHI DEMO里面那样,
    比较成熟的做法可以用COM+,
    1,将COM对象加入组件服务,
    2,这个COM对象要支持IObjectControl接口 (mtx单元)
      

  8.   

    Object Pooling,COM+不是直接支持吗?还要用MTS干嘛?
    另外,如果用OOP的方法,那怎么处理更新错误?如果用RAD,可以上TClientDataSet.OnReconcileError事件中处理,但如果用OOP封装了更新操作,那如何处理?