ServiceObject通常都應該是無狀態的,即它使用完放入Pool中,另一個調用再啟用它時,每次的執行行為都是一樣的,不會用到上次調用所保留在記憶體中的某些資料,因為元件被啟用調用的順序是隨機的,可能這次被A用戶端啟用,再次被B用戶端啟用,下次又被A用戶端啟用。如果保留狀態,需要非常注意狀態是如何被利用的。
但並不是說元件一定不能有狀態,根據一些特殊的需要,你可以自己保留元件的狀態。如,我們考慮設計一個記憶體中編號產生器,每次元件啟用調用GetNewOID,就得到一個新的編號,這些編號是連續的,所以我們在元件的內部有個當前編號變數,每次加1:TOIDServiceObject=class(TServiceObject)<br />private<br /> FCurrentOID:integer;<br />published<br /> function GetNewOID(const AParams:OLEVariant;AASyncCallContent:TASyncCallContent):OLEVariant;<br />end;</p><p>function TOIDServiceObject.GetNewOID(const AParams:OLEVariant;AASyncCallContent:TASyncCallContent):OLEVariant;<br />begin<br /> Inc(FCurrentOID);<br /> Result:=FCurrentOID;<br />end;
當然,這個元件要求是單一執行個體的,才能達到如期效果,否則,需要把FCurrentOID屬性移到元件之外。
有狀態的一個特別的應用是用戶端來控制資料庫的Transaction。
1、當用戶端調用BeginTransation時,伺服器的DBServiceObject元件使用其TADOConnection.StartTransaction啟動Transaction,並返回給用戶端這個DBServiceObject的標識:ServiceObjectStub。同時伺服器鎖定這個DBServiceObject元件,不把它分配給別的用戶端調用。
2、在用戶端再次調用CommitTransaction或RollbackTransaction時,需要同時把ServiceObjectStub傳遞給伺服器,伺服器尋找到那個DBServiceObject,然後使用TADOConnection來執行CommitTransaction或RollbackTransaction。同時伺服器解除對這個元件的鎖定。
因為是用戶端控制的Transaction,同樣可能因為通訊的問題,用戶端發起BeginTransaction之後,可能網路的原因或者自己當機就再也無法與伺服器通訊了,伺服器需要設定一個時間來自動解鎖那些被長時間鎖定的DBServiceObject。基於此,一般建議用戶端不要來控制Transaction,盡量交給ServiceObject內部來控制。