CnPack Forum


 
Subject: CnPack的数据库连接池组件这样使用对吗?
yusea
新警察
Rank: 1



UID 41930
Digest Posts 0
Credits 5
Posts 1
点点分 5
Reading Access 10
Registered 2009-3-5
Status Offline
Post at 2009-3-6 14:55  Profile | Blog | P.M. 
CnPack的数据库连接池组件这样使用对吗?

我把我使用的方法,打了个包,请大家指点一下,正确的用法?


Attachment: 数据库连接池示例.rar (2009-3-6 14:55, 12.78 K)
Download count 658
Top
zzzl (早安的空气)
版主
Rank: 7Rank: 7Rank: 7



UID 590
Digest Posts 0
Credits 399
Posts 199
点点分 399
Reading Access 100
Registered 2004-11-29
Status Offline
Post at 2009-3-12 10:49  Profile | Blog | P.M.  | QQ
没有用过,帮你顶啊
Top
shenloqi
灌水处处长
Rank: 4



UID 34
Digest Posts 1
Credits 287
Posts 179
点点分 287
Reading Access 10
Registered 2003-3-15
Status Offline
Post at 2009-3-13 11:29  Profile | P.M. 
这个连接池组件是从对象池继承的。

下面的函数解释了GetResult的各个含义:
function grToStr(const gr: TCnObjectPoolGetResult): string;
begin
  case gr of
    grSuccess: Result := '成功获得一个池对象';
    grReuse: Result := '获得一个正在使用的池对象'; //该对象其他地方也正在使用,意味着可能要处理多线程和维护正确的状态等问题
    grReinitFail: Result := '池对象初始化失败'; //意味着可能需要重新获取别的对象,或者用自己的方法重新初始化该对象
    grGetFail: Result := '获取池对象失败'; //一般在池被释放的时候获取,或者是在用户的OnGetOne方法中返回一个False,或者是PolicyOnBusy为bpGetFail且池处于Busy状态的时候,或者PolicyOnPeak为bpGetFail且池处于Peak状态的时候才会返回GetFail,由于此状态由用户控制,所以如果GetFail了,应该怎么处理也应由用户处理
    grGetError: Result := '获取池对象出现内部错误'; //当从池中获得的对象不是预期的对象时会返回该状态,一般不会出现该问题,除非用户错误的释放了池中的对象或其他原因导致了池中的对象指针不再有效时才会出现该状态
    grWaitFail: Result := '在获取池对象时等待超时'; //当设置PolicyOnBusy和PolicyOnPeak为bpGetWait时,等待超过了WaitTimeOut属性设置值时,停止等待,并返回该状态
  else
    Result := 'Unknown';
  end;
end;


对于一个ADOConnection来说,一般情况下,Connection可以被多个Query等使用,所以goNone是可以的,如果不希望一个连接被多个Query等同时使用,那么GetOption设置为goReInit或goMutex比较合适,由于一个ADOConPool中的所有的ADOConnection对象在被获取时其连接串都与设置好的连接串相同,所以该ADOConnection很多时候都可以继续维持Open状态,并等待下一次使用(下次使用就无需重新连接了),所以goMutex会更合适(goReInit会在每次获取到ADOConnection的时候都重新尝试Connect,这样速度上肯定会有所影响),但是当连接经常容易断或者其他原因需要每次得到连接时都要重新连接的话,那么使用goReInit会更合适。


在使用完一个ADOConnection之后,可以通过ReleaseOption来通知池如何处理该对象,有roNone, roReInit, roDelete, roFree四种,roNone就是什么都不干,roReInit就是要该对象在下次被获取时重新初始化该池对象(如果该池对象正在使用了多次,那么该池对象会等到所有使用者都归还该对象之后当再次被使用时初始化以防止初始化引发其他使用者出现问题),roDelete是当用户由于某种原因已经将该池对象释放了的情况下,需要通知池不要再维护该对象了,池就会直接从池中删除该对象的引用,roFree跟roDelete的区别在于roFree负责释放池对象(用户可以通过OnFreeOne方法自行负责释放该对象)并删除池对该对象的引用。注意roDelete和roFree都是特殊情况备用的,所以roDelete和roFree都不管是否有多个使用者正在使用该池对象而直接处理。


池的属性中PolicyOnBusy是指池中所有对象都被使用的情况下池所采取的策略,可以是等待,或者直接返回GetFail或者是重用池的正在使用的对象(有些对象是可以重用的或者部分重用,但是绝大部分对象要小心重用带来的副作用)。
PolicyOnPeak是指池不但忙,而且所有的池对象都被重复使用到了设置的最大重用数的情形下该采用的策略,可以为等待或者直接返回GetFail。


至于PolicyOnGet就是优先获取池中的什么对象的策略了,可根据该对象的负载和运行效率或者运行次数多少等决定。


此外,ADOConPool使用是池化了各个ADOQuery/Table等组件所依赖的Connection组件,像楼主的例子中的ADOQuery.ConnectionString := ADOPool.ConnectionString这种方法显然是不能利用池组件的优势的。
而由于ADOConPool本身也不是Connection类型的组件,所以也不能直接在IDE中通过设置Query等组件的Connection到ADOConPool。而且ADOConPool本身也不是用于这种情况的。(如果像普通的程序,只有一个连接,有多个Query连着这个Connection,那根本无需ConPool)


ADOConPool一般是用于后台服务程序的,在程序中每次创建和释放Connection的开销比较大,而只使用一个全局的Connection,可能又会出现性能问题,或者出现争用的情况(或者如前所述,可能会出现需要自己ReConnect),那么这时候ADOConPool就可以用上了(我以前是用一个单元封装连接池,该单元根据项目要求只对外提供简单的GetConnection和ReleaseConnection方法)。
当用在多线程程序时需要注意,可能有些ADO提供者提供的ADOConnection不能跨线程使用,如果是这样,由于连接池创建出来的连接的创建线程不能保证和使用线程是同一个,可能会出现问题(不过很多时候,只要不存在多线程同时使用一个连接的情况,就不会出现问题,也就是说,在这种情况下,用goMutex方法保证一个池连接不会同时被多个线程拥有就可以了)。


具体的应用场景需要自己去体会啦,但是该组件的设计意图不是用来替换Delphi在设计客户端程序时候的Connection/Query这种方式的。
Top
jAmEs_
灌水部部长
Rank: 8Rank: 8



Medal No.1  
UID 886
Digest Posts 0
Credits 1134
Posts 600
点点分 1134
Reading Access 10
Registered 2005-6-5
Location 广东
Status Offline
Post at 2009-3-31 09:33  Profile | Blog | P.M. 
說的很詳細,但是始終對連接池用處不感冒~~~
Top
 




All times are GMT++8, the time now is 2024-11-22 06:49

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.008847 second(s), 10 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP