为何客户端的ClientDataSet每次Open/Refresh都会导致所连接的COM+实例重建? ( 积分: 100 )

  • 主题发起人 主题发起人 BBM011
  • 开始时间 开始时间
B

BBM011

Unregistered / Unconfirmed
GUEST, unregistred user!
TClientDataSet在Open和Refresh时,都不会使用已有连接的COM+对象,而是会新建一个COM+实例,也就是说我前面调用服务器的接口并通知它客户端标识就没用了,因为这时候访问到的COM服务器已不是以前的那个了。 我不想他新建COM+实例,请问怎样解决啊?
 
TClientDataSet在Open和Refresh时,都不会使用已有连接的COM+对象,而是会新建一个COM+实例,也就是说我前面调用服务器的接口并通知它客户端标识就没用了,因为这时候访问到的COM服务器已不是以前的那个了。 我不想他新建COM+实例,请问怎样解决啊?
 
参考
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1491917
标题: Midas配合COM+编程,为何客户端的ClientDataSet每次Open/Refresh都会导致所连接的COM+实例重建?
-----------------------转自网络
----------------------------
Sachow (2002-12-07 17:33:00)
你的这样想法,实际上是与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数据库我就不知道怎么做了。


----------------------------
TClientDataSet方面在取得数据时使用BeforeGetRecords事件,在更新数据时使用
BeforeUpdateRecord事件,TDataSetProvider方面也有对应的事件,灵活使用这
些事件应该能够满足你的需要了,在Delhpi的帮助中输入“TRemoteEvent type”
还可以查到增量(分段、多次)读取数据的例子。在《Delhpi5.x ADO/MTS/COM+
高级程序设计篇》的第10章中,有更详尽的例子。
至于是否自己建立一个继承自TClientDataSet的控件以适应你的业务逻辑,这要
你自己根据具体情况而定:这种业务逻辑需求是否有普遍性,是否会在多个项目
中采用,只有复用价值高的东西才值得封装为控件。而且,将它封装为控件将占
用你更多的时间来进行开发和测试,以适应不同的业务逻辑需求,你需要权衡一
下自己是否有那么多时间来完成这项工作。
 
问题是我现还没解决啊
 
COM+实例的增加应该不是和ClientDataSet的Open有关吧。。。。
TDcomConnect的连接和断开会导致COM+实例的增加、减少的。
如果你没有在Clientdataset打开后断开Dcom连接,是不会增加Com+实例数量的。
ClientDataSet的Open,Close会导致数据库中的连接增加和减少。(如果是使用SQL Server的话,你可以在企业管理器中的“当前活动”中查看连接数量的变化)
 
to: weic
我在TDcomConnect连接后就没有断开,我调试一下就会发现问题的.
 
没有人出来回答吗?没有人出来回答吗?
 
我新作了一个小例子试了一下。
中间层是ActiveX Libary+ Transationc Data Mudule,Require Transation
客户端是DcomConnection+ClientdataSet。
客户端先将DCOMConnection.connected:= True;
然后反复执行ClientDataset.Close+OPen;或者是Open后,反复执行REfresh,当前激活组件就是一个。
没有重复出你说的现象。
 
你定义一个公共变量 Sqlstr:string;
Sqlstr:=;//数据库连接字符串
在MtsDataModuleCreate事件里代码如下://
ADOConnection1.ConnectionString:='';
写一个接口代码如下://连接COM+对象之前要先执行下面的代码
ADOConnection1.ConnectionString:=Sqlstr;
然后写一个接口创建TADODataSet,TDataSetProvider之类的ADODataSet.Connection:=ADOConnection1;
最后在客户端调用
这样写你就会发现有这情况出现了,就如下面所说的
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1491917
 
如果你遇到的问题和上述那个帖子的内容一样,那我也没什么可说的了。
说实在的,你的用法本身就很奇怪。
先 方法1(设置数据库连接),在保持连接的情况下,调用方法2......等等。
你的问题就出现在,你的第一个函数上。
一般COM+的组件是无状态组件,如果是针对客户端提供的接口函数,其内部必然是这样编写的:
procedure XXXXXXXX;
begin
try
{
这里是你的代码。s
}
SetComplete;
except
setAbort;
end;
end;

如果你的接口函数中只是一句赋值,这个COM+本身没有被释放,保持了连接,就会出现你说的现象,每连一次产生一个。
但是如果你按照上面的写法,则调用完方法1之后,COM被释放了。再调用时,原来设置的SQL连接串已经不见了。不符合你的要求。
所以,最终你的问题的答案是。你的用法导致了COM+的运行状态。并不是ClientDataset有什么问题。
而且在客户端设置COM连接数据库连接串的方式不知是什么用意?必须这样?
 
接受答案了.
 
后退
顶部