Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


A Design Pattern for Creating Reusable COM+ components using Visual Basic and XML : Page 4

Over the last year or two, quite a few articles and books have been written on COM+, transaction management, and programming stateful & stateless components, explaining in detail what COM+ does and how it does it. When tasked with creating a model for developing lightweight, reusable components, you can found a lot of What-not-How type of articles on COM+, but not a lot of practical How-To type of articles. The author started working through a lot of information on COM+, combined this information with how I wanted a reusable component to behave, and came up with a real easy model for creating reusable COM+ business objects.


Starting to benefit from reuse

Let us now look at a slightly more complex sample of reuse. In our Insurance project the contract can have multiple clients associated with it.  We want to reuse our Client component to provide a collection of Client objects, and these objects must be accessible on both the BO and CO layers of our Insurance project.  The CO level of the insurance object will reuse our clsClient object, while the BO level of the insurance object will reuse clsClientSVR.  Thus the ContractBO project has to reference the ClientBO project, and the ContractCO project has to reference the ClientCO project.  Note that the only CO project to reference ClientBO is ClientCO.

The relationship between Contract and Client is many-to-many.  I implement this link using a table called ContractClients.  I do not use a compound key for this table, as updating changes to a table with compound keys can become a total nightmare if any one of the key fields changes.  I implement clsContractClient to map to a row in this table, and the collection class colContractClients that will Load all the ContractClient records for a specified contract.  Depending on your business logic, you may decide to Load the corresponding Client object either on first reference, or every time clsContractClient is loaded.  I chose to Load the corresponding Client object in clsContractClient.Load,

The collection class colContractClients takes as parameter the primary key of the contract, and then fetch the primary keys of all the clients associated with this contract, loads these clsContractClient objects and then adds them to the collection.  The advantage of this approach is total encapsulation of my Client object.  There is only one method to load my client object and one method to save it, meaning fixing an error or adding functionality to my Client object has to be done only in clsClientSVR.  The disadvantage of this approach is that, in order to load n clients I will always have n+1 queries to SQL.  In most cases it is possible for the collection class to select all the necessary information in one query and to push this information into the client objects, but that means you need to know exactly how clsClientSVR expects its data, which is not possible if you are aiming for binary reuse.  It boils down to a tradeoff between speed and maintainability/reusability, and I chose the easier maintainable option.  The code for f_LoadAll and LoadAll of colContractClientsSVR is shown below.  As is the case with all other code, f_LoadAll is for use by the CO level object while LoadAll performs the actual work and can be used by other BO level objects.

Public Function f_LoadAll(ByVal pstrConnection$, ByVal plngContractID As Long, ByRef pstrXML$) As Boolean Dim lobj As ContractBO.clsClientSVR f_LoadAll = LoadAll (pstrConnection, plngContractID) pstrXML = Pack End Function Public Function LoadAllObjects(ByVal pstrConnection$, ByVal plngContractID As Long) As Boolean Dim lstrSQL$ Dim lobjClient As ClientBO.clsClientSVR Dim lobjSQLRead As ContractBO.clsSQLRead Dim lobjRS As ADODB.Recordset Dim lobjMTS as ObjectContext: Set lobjMTS = GetObjectContext() Set lobjSQLRead = New ContractBO.clsSQLRead lstrSQL = "Select ClientID from ContractClients where ContractID = " & plngContractID lobjSQLRead.ExecuteRS pstrConnection, lstrSQL, lobjRS Set mobjColl = New Collection While Not lobjRS.EOF Set lobjClient = lobjMTS.CreateInstance(ClientBO.clsClientSVR) If lobjClient.Load(pstrConnection,(lobjRS!ClientID)) Then Add lobjClient End If lobjRS.MoveNext Wend Set lobjRS = Nothing Set lobjSQLRead = Nothing End Function

The collection class colContractClients provides you with two functions to retrieve objects from the collection, either by primary key (ItemByKey) or by position (ItemByPosition) It also provides an enumerator function. In order to be able to enumerate the collection, you have to set the Procedure ID of the NewEnum function to 4. To set this property, load the project in VB, go to the object browser (F2) and select the project ClientBO. It will then list all your classes in the left pane. Select colContractClientsSVR, and all properties and methods will appear in the right pane. Select NewEnum, right-click and select "Properties" from the pop-up menu. Click on the "Advanced" button, and set "Procedure ID" to 4. As a neat touch, I also like to hide the NewEnum function, so click on "Hide this member" if you share my sentiments. Repeat above steps for colContractClients on the CO layer.

Loading our Contract now becomes a slightly more complex affair, and it is done in 4 steps.

  1. clsContractSVR.Load selects the contract data and loads it into the private variables of clsContractSVR
  2. The LoadAll method of colContractClientsSVR is called. This method selects the primary key field of every clsContractClientSVR object in the collection, and then calls the Load method for each of these.
  3. clsContractClientSVR.Load loads its data into the private variables and then calls the Load method on its private instance of clsClientSVR
  4. clsClientSVR.Load loads the client data into the object

Although the above forms a long chain, it is pretty straightforward OOP programming. We now have the ability to load a rather complex object hierarchy in memory on our COM+ machine. The next step is to transport this hierarchy to the CO level.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date