Midas配合COM+编程,为何客户端的ClientDataSet每次Open/Refresh都会导致所连接的COM+实例重建?(200分)

  • 主题发起人 主题发起人 WiseAnt
  • 开始时间 开始时间
W

WiseAnt

Unregistered / Unconfirmed
GUEST, unregistred user!
我已经大致搞清楚了COM+中SPM(共享属性管理)这个东东,也做了到了COM+组件之间共享信息。我让客户端在创建一个DCOM连接时通知COM+服务器自己的客户标识,COM+服务器便可以正确的连接到指定的数据库。
但问题不在这儿!!!
当我很高兴的认为问题可以很好的解决时,却发现TClientDataSet在Open和Refresh时,都不会使用已有的Dcom连接所连接到的COM+对象,而是会新建一个COM+实例,也就是说我前面调用服务器的接口并通知它客户端标识就没用了,因为这时候访问到的COM服务器已不是以前的那个了。
大家可以到http://www.playicq.com/dispdoc.php?id=2312下载我的示例代码,可以看到我的示例中使用COM+提供的接口函数是没问题的,我觉得问题出在clientDataSet身上。
不过,我想可能clientDataSet这样做也有它的道理,因为ClientDataSet.Open以后,已将数据取到了客户端,而此时如果还不断开COM+连接,将必然减少COM+所能同时服务的客户数量,所以在Open或Refresh后,它将COM+实例销毁了,只到客户端需要进行下一个动作(如applyUpdates)时,才又连上去,大的增加了灵活性。
可这并不是我所想要的,难道我们每次Open/Refresh/ApplyUpdates之间都要传递ADO数据库连接串给后台,告诉它客户端要连接到的数据库吗?这样可是会死人的。或者我们就只能将数据库连接写死在程序或INI文件中了吗?
 
可以直接到以下地址下载示例:
http://www.playicq.com/databack/spmdemo1.rar
另外还有一个关于调试COM的录像,用的就是这个示例
http://www.playicq.com/dispdoc.php?id=2313
 
可以将COM+做成 Win2000 的一个服务程序。
或者做一个对象池。缓存对象,就不会每次都创建新的Com对象了。
 
COM+,delphi的优点你居然不用;
 
to 1Fuyi:
>>可以将COM+做成 Win2000 的一个服务程序。
是不是做成一个进程外服务器?我不想的。
>>或者做一个对象池。缓存对象,就不会每次都创建新的Com对象了。
我认为缓存对象也是一样的,试想一个缓存对象肯定不会为客户端维护信息,不可能保存下来
各客户端目录存取数据的状态或数据库,就算是缓存对象也得将客户端的上次状态或标识传给它。
你有这方面的示例吗?
to 卡色:
 >>COM+的优点你居然不用;
小弟接触COM+不久,希望你能说得清楚一些,好吗?

 
我想让COM+服务不同的客户端连接到不同的数据库,比如在COM+中提供了以下四个接口函数:
LogonIn(连接COM+并设置数据库连接)
GetCusts(读取客户资料)
UpdCusts(更新)
AddCusts(增加)
我只想在LogonIn确定数据库连接,而在后面调用三个函数时,不要再Logon
但从利用COM+资源以便服务更多客户端的角度出发,我在调用了一个接口后,应该断开跟COM+的连接,直到下次要用时再连接COM+,也就是跟Pooling差不多的概念了。
这样的话,问题就出来了,因为我在调用一个接口时,已不是上一次连接的COM+对象了,我必须先LogonIn,然后再调用UpdCusts方法。
比如,我想:LogonIn->GetCusts->UpdCusts
而其实却要:LogonIn->GetCusts|LogonIn->UpdCusts
各位认为如何?
 
我都还没接触呢!只是来混分巴了!
LogonIn(连接COM+并设置数据库连接)连接COM+是需要的,设置数据库连接用不着了吧!
之后……
GetCusts(读取客户资料)
(不懂的说,对COM和DCOM了解一点,还是期待高手吧),
怎么收到病毒~~~~~~~~~:)
 
to WiseAnt:
-------比如,我想:LogonIn->GetCusts->UpdCusts
-------而其实却要:LogonIn->GetCusts|LogonIn->UpdCusts
从你的描述来看,你的COM+对象是无状态的。
 
[:(]
没研究过, 帮不上你
找李维的那本《ADO/COM+。。。。》看看能否帮上你吧
 
ClientDataSet是不会持续连接的,用完了就断开。
 
呵,这是优点.也就是所谓无状态对象,这样就能实现对象缓冲池等诸多好处.
三层都讲究这个,比如EJB,跟delphi三层一样,推荐stateless.
 
感谢各位捧场!
to 郭玉梁:
  在DCOM环境下测试,ClientDataSet并不会用完就断开,在COM+下才会这样!
有没有办法让COM+象DCOM那样看起来就象状态对象一样维护客户端的信息。
  我在客户端将ClientDataSet设为分段读取数据,可在Delphi7调试环境中发现COM+还是会
创建一个新实例(可能并不是新实例,而只是相当于Stub的东西,而实例是缓存在内存中的),
我认为COM+与每一客户端之间一定存在一个象唯一标识这样的东西,根据这个再取得所维护的
客户端状态,所以COM+服务器才会知道下一次要读取的数据。是吗?
  我一直想,如果能够得到这个COM+服务器与客户端之间进行通讯的唯一标识的话,问题就
解决了,我可以在客户端登录时,创建SPM,记录下客户标识,以后的过程中就根据这一标识从
SPM中读取所要的信息...
某一客户端下一次所要读取的数据,
 
你的这样想法,实际上是与COM技术的无状态服务器思想所背道而驰的。所谓无状态服务器
就是指服务器端不负责维护客户端打开的数据库连接、数据库光标及其它对话信息等,从而
增加能同时服务的客户端的数量。但这不表示我们就无法实现业务逻辑的连贯性操作,关键
是要客户端程序自己维护状态信息,即客户端程序自己记录上次所读取的数据表的光标所在
位置,下次存取的时候从该光标位置开始,相应程序代码应加在TClientData的BeforeGetRecords
事件和TDataSetProvider的BeforeGetRecords事件中。(详情请参考《Delphi 5.x分布式多
层应用系统篇》第5章第1节)
以我的想法:为了配合COM的无状态服务器原则,你不应该考虑让服务器知道某客户端是否
已经登录了,并帮它维护状态,而应该换一个思路,即:服务器端只以一个Login方法用于
验证客户端是否有权使用本系统,客户端判断调用Login方法的结果,如果验证通过,就继续
运行程序,并根据某些配置信息来决定该连接那个数据库。换句话说,服务器调是不设防的,
让客户端通过调用Login方法的结果来设防吧。[服务器端不设防,这样安全吗?呵呵,安全
方面的事宜交由DCOM/COM+的安全机制来负责,大家不是嫌DCOM麻烦吗?不麻烦怎么能够安全
呢?]
其它:如果你要动态连接到不同的数据库,在Oracle数据库中我知道可以采用数据链的方式,即
Select XXX From YYY@[TNSNAME]这种方式,使用SQL Server数据库我就不知道怎么做了。
 
客户端自己维护状态,意思是这样,具体怎么做,毫无头续!
 
其实也不能说毫无头续,因为各位的帮助,特别是Sachow大侠的见解(可惜Sachow大侠好象没有订Email通知)
我感觉是有一点认识和想法了。
ClientDataSet.Open/Refresh会发生OnBeforeGetRecords
ClientDataSet.ApplyUpdates同样会发生OnBeforeApplyUpdates
同样的事件还有OnBeforeGetParams等等...
  而在这两个事件中都有一个var OwnerData参数,这个值可以传给后台的TDataSetProvider控件,
我们可以在客户程序启动时调用服务器的LogonIn接口得到一个唯一标识,保存在客户端,然后在上面
的事件中通过OwnerData传给COM+服务器(有点象Cookie一样),这样的话,就做到了象有状态对象一样
看似维护了客户端的信息。
  各位大侠以为如何?不知道除了这几个TClientDataSet提供的事件以外,是否还有别的地方应该处理,
而TClientDataSet又没有提供控制的地方?
  另外,我想从TClientDataSet派生一个类,将这几个事件的处理写到内部,这样的话能够进一步简化
每一个客户端的clientDataSet的统一及安全性,各位认为如何?
 
midas提供很多机制可以传递额外数据,
但即使如此,由于你的客户端操作的数据库可能不同,
每次操作还是要进行数据库的连接,比较烦。
 
当然还有别的地方应该处理,TClientDataSet很全面了,看看
《Delphi 5.x分布式多层应用系统篇》吧,我看过,不过没做过项目,现在
几乎忘的差不多了!
 
后退
顶部