ServiceObject通常都应该是无状态的,即它使用完放入Pool中,另一个调用再激活它时,每次的执行行为都是一样的,不会用到上次调用所保留在内存中的某些资料,因为元件被激活调用的顺序是随机的,可能这次被A客户端激活,再次被B客户端激活,下次又被A客户端激活。如果保留状态,需要非常注意状态是如何被利用的。
但并不是说元件一定不能有状态,根据一些特殊的需要,你可以自己保留元件的状态。如,我们考虑设计一个内存中编号产生器,每次元件激活调用GetNewOID,就得到一个新的编号,这些编号是连续的,所以我们在元件的内部有个当前编号变量,每次加1:
当然,这个元件要求是单一实例的,才能达到如期效果,否则,需要把FCurrentOID属性移到元件之外。
有状态的一个特别的应用是客户端来控制数据库的Transaction。
1、当客户端调用BeginTransation时,服务器的DBServiceObject元件使用其TADOConnection.StartTransaction启动Transaction,并返回给客户端这个DBServiceObject的标识:ServiceObjectStub。同时服务器锁定这个DBServiceObject元件,不把它分配给别的客户端调用。
2、在客户端再次调用CommitTransaction或RollbackTransaction时,需要同时把ServiceObjectStub传递给服务器,服务器寻找到那个DBServiceObject,然后使用TADOConnection来执行CommitTransaction或RollbackTransaction。同时服务器解除对这个元件的锁定。
因为是客户端控制的Transaction,同样可能因为通讯的问题,客户端发起BeginTransaction之后,可能网络的原因或者自己当机就再也无法与服务器通讯了,服务器需要设定一个时间来自动解锁那些被长时间锁定的DBServiceObject。基于此,一般建议客户端不要来控制Transaction,尽量交给ServiceObject内部来控制。