Using COM +
Transactions
I
n this c hapter, I’ll sho w yo u ho w to c reate a COM+ transac -tio n. These transac -tio ns c an be used to implement an n-tier applic atio n system, whic h c an o ffer signific ant perfo rmanc e impro vements when c o mpared with mo re traditio nal c lient/ server applic atio ns.A Brief Overview of COM +
Writing a COM+ pro gram isn’t diffic ult. If yo u understand ho w to c reate and use a Class mo dule, then writing a COM+ trans-ac tio n isn’t muc h mo re diffic ult than that. Ho wever, to write an effec tive COM+ applic atio n means that yo u need to kno w what COM+ is and ho w it wo rks.
M ulti-tier applications
In a traditio nal c lient/ server applic atio n, the c lient c o mputer c o mmunic ates direc tly with the database server ( see Figure 18-1) . This is also kno wn as a 2-tier applic atio n pro gram.
Figure 18-1: A 2-tier application Client Computer
Database Server
1 8
1 8
✦
✦
✦
✦
In This Cha pter
Reviewing the CO M+ transactio n architecture
Meeting the ACID test
Co nstructing CO M+ transactio ns
Building a test pro g ram
By using COM+ transac tio ns, yo u c an implement a 3-tier so lutio n. In prac tic e, yo u have a c o mputer fo r the c lient, a sec o nd o ne fo r the COM+ transac tio n server, and a third o ne fo r the database server ( see Figure 18-2) . No te that the transac tio n server generally sits between the applic atio n c lient and the database server.
Figure 18-2: A 3-tier application
The transac tio n server is a plac e where yo u c an mo ve yo ur applic atio n lo gic away fro m the c lient pro gram yet keep it independent o f the datab ase server. This allo ws mo re flexib ility when designing yo ur applic atio n, b ec ause yo u c an pro vide an o b jec t-o riented view o f yo ur data, while making availab le fac ilities that allo w yo u to share reso urc es fo r b etter perfo rmanc e and permit transac tio n suppo rt fo r b etter reliab ility.
A mo re interesting so lutio n is sho wn in Figure 183. While I’ve labeled it a 4tier pro -c essing so lutio n, mo st peo ple -c o nsider it just ano ther variatio n o f a 3-tier so lutio n, bec ause they feel that the c lient c o mputer running a Web bro wser is no t a true tier. Ho wever, given ho w easy it is to add VBSc ript o r JavaSc ript to the Web page to per-fo rm basic func tio ns like data validatio n, why no t c o nsider it a true tier?
In general, yo u c an refer to multi-tier so lutio ns as n-tier, where nrefers to the num-ber o f levels o f c o mputers used in the applic atio n design. No te that I do n’t simply c o unt the number o f c o mputers, bec ause it is quite po ssible to have mo re than o ne Web server, mo re than o ne transac tio n server o r mo re than o ne database server that pro vides the same basic servic es, but are implemented o n multiple c o mputers to better handle the wo rklo ad. With ntier so lutio ns, eac h level o f c o mputers pro vides a new type o f servic e. In prac tic e, ho wever, eac h new level o f c o mputers intro -duc es additio nal o verhead and beyo nd the fo ur c o mputers sho wn in Figure 18-3, it is do ubtful that yo u wo uld gain any additio nal benefit fro m adding a new tier.
Figure 18-3: A 4-tier application
Transaction Servers
The transac tio n server rec eives req uests fro m the pro gram running o n the c lient and starts a transac tio n to pro c ess it. If info rmatio n is needed fro m the datab ase server, the transac tio n will c o mmunic ate with the datab ase server. When the transac tio n has finished pro c essing, it will return b ac k to the c alling pro gram.
Adding the third tier, yo u o fflo ad so me o f the wo rk fro m the database server, whic h allo ws the database server to perfo rm additio nal wo rk o n the same hardware c o n-figuratio n. It also simplifies updating the applic atio n, sinc e it is po ssible to make c hanges to a transac tio n o n the transac tio n server witho ut c hanging the c lient pro -gram that c alls the transac tio n.
In a 4-tier so lutio n, using a transac tio n server makes even mo re sense. It allo ws yo u to o fflo ad wo rk fro m bo th the Web server and the database server o nto a separate c o mputer system, whic h serves to impro ve respo nse time o n bo th mac hines. This allo ws yo u to inc rease the available memo ry fo r Web page c ac hing and database rec o rd c ac hing.
Web Server Client Computer
Typic ally, the database server, transac tio n server, and Web server ( if present) are all c o nnec ted via a very high-speed c o nnec tio n. At least a 100 MHz Ethernet, if no t a gigahertz Ethernet o r o ther spec ialized netwo rking tec hno lo gy, is used to c o nnec t these c o mputers to gether. Often this netwo rk is iso lated fro m the o ther netwo rks to impro ve sec urity and perfo rmanc e. This means that there are very few delays c aused by the netwo rk. Yet by spreading the wo rk aro und, yo u c an ensure that no o ne system is o verlo aded. Yo u c an even add additio nal Web servers and transac -tio n servers transparently if yo u really need them witho ut requiring c hanges to yo ur applic atio n.
COM + applications
A COM+ transac tio n is basic ally a COM o bjec t that has been c o ded and c o mpiled to run under the COM+ transac tio n server. In Visual Basic , yo u c reate a COM+ trans-ac tio n by building an Ac tiveX DLL applic atio n. Yo u need to inc lude a few spec ial o bjec ts and add a little c o de to perfo rm so me handshaking with the transac tio n server and use a spec ial to o l to define yo ur transac tio n to the transac tio n server. But o ther than that, yo u’re free to take advantage o f the Visual Basic language.
A COM+ applic atio n is just a c o llec tio n o f o ne o r mo re COM+ transac tio ns that are gro uped to gether into a single Ac tiveX DLL file. There are fo ur basic types o f COM+ applic atio ns:
✦Se rve r applications: A server applic atio n is the mo re c o mmo n fo rm o f a COM+ applic atio n. It runs under c o ntro l o f the transac tio n server. The applic a-tio n c an interac t with the transac a-tio n server thro ugh the o bjec ts asso c iated with the transac tio n’s c o ntext.
✦Library applications: A library applic atio n is a spec ialized fo rm o f a COM+ applic atio n that runs lo c ally o n the c lient c o mputer. It runs in the same address spac e as the c lient pro gram that c reated it. This means less o verhead to the c lient pro gram, bec ause several COM+ applic atio ns c an use the same c o mpo nents. Ho wever, bec ause this o bjec t isn’t running under the c o ntro l o f the transac tio n server, it c an’t take advantage o f so me o f the features o f the transac tio n server.
✦Application proxie s:An applic atio n pro xy c o ntains the registratio n info rma-tio n nec essary fo r an applic arma-tio n to remo tely ac c ess a server applic arma-tio n. If yo u run it o n the c lient c o mputer, all o f the info rmatio n nec essary to ac c ess a spec ific remo te server applic atio n will be installed o n the c lient c o mputer.
✦COM+ pre installe d applications: COM+ c o mes with a set o f applic atio ns that help yo u c o nfigure and administer yo ur COM+ system. These applic atio ns inc lude COM+ System Administratio n, COM+ Utilities, and IIS System Applic atio ns.
The COM + transaction server
The COM+ Transac tio n Server pro vides a framewo rk to exec ute transac tio ns o n an n-tier applic atio n system. Inc luded with the Server are fac ilities that allo w yo u to share reso urc es, suc h as ASO Connectiono bjec ts, and pro vide additio nal sec urity o n yo ur transac tio n.
Yo u c an o nly run the COM+ Transac tio n Server under Windo ws 2000 Server. Yo u c an’t run it under Windo ws 9x, Windo ws NT, o r even Windo ws 2000 Pro fessio nal. It relies o n fac ilities, suc h as the Ac tive Direc to ry, to manage muc h o f the info rmatio n it needs to run yo ur transac tio ns. Bec ause the COM+ Transac tio n Server represents o nly o ne tier in an applic atio n, yo u c an use any database server yo u c ho o se, even if it runs under a different o perating system suc h as Unix. The o nly restric tio n is that the database server must be suppo rted by ADO.
Serving transactions under Windows NT: If you w ant to run transactions under Window s NT Server, you need to use a tool called Microsoft Transaction Server, usually called MTS. Many of the basic facilities in MTS w ere upgraded to create COM+ , but COM+ is not upw ards com patible w ith MTS. COM+ requires less code to interact w ith the transaction server and is easier to adm inister than MTS.
The object context
Every COM+ transac tio n that is run under c o ntro l o f the COM+ Transac tio n Server is asso c iated with a set o f o bjec ts kno wn as a co nte xt. A c o ntext represents the smallest po ssible unit o f wo rk fo r a c o mpo nent. Eac h instanc e o f a COM o bjec t is assigned to a c o ntext. Multiple o bjec ts c an use the same c o ntext depending o n ho w they were defined and c reated.
The o bjec t c o ntext c o ntains info rmatio n abo ut ho w the o bjec t was c reated and the status o f the wo rk that is c urrently ac tive. Yo u c an ac c ess these fac ilities thro ugh the ObjectContexto bjec t. All o f the o ther o bjec ts in the c o ntext c an be referenc ed fro m this o bjec t either direc tly o r indirec tly.
The Component Services utility
The Co mpo nent Servic es utility is used to manage and c o nfigure COM+ transac -tio ns ( see Figure 18-4) . Yo u c an start it in Windo ws 2000 by c ho o sing Pro grams➪
Administrative To o ls➪Co mpo nent Servic es fro m the Start butto n. This to o l will be used frequently while testing yo ur applic atio n to c hange the c harac teristic s o f the transac tio n, as well as to install updated c o pies o f the COM c o mpo nent that makes up yo ur COM+ applic atio n.
Figure 18-4: Running the Com ponent Services utility
Introducing COM + Transactions
COM+ transac tio ns are a feature o f Windo ws 2000 that yo u c an use when b uilding sc alab le, n-tier applic atio ns. COM+ is b uilt o n to p o f COM and integrates features suc h as the Mic ro so ft Transac tio n Server and Mic ro so ft Message Queues into a single tec hno lo gy.
COM+ is built using C++ and so me o f its features c an o nly be ac c essed fro m C++. Ho wever, this do esn’t mean that yo u c an’t use COM+ fro m Visual Basic 6. In fac t, many o f the features are ac tually very easy to use, o nc e yo u understand ho w to wo rk with them. Bec ause this bo o k is aimed at Visual Basic pro grammers, I’ll fo c us o n the features yo u c an explo it to day and leave the rest fo r the C++ pro grammers.
A view of things to come: As I w rite this, there are m any rum ors surrounding the features that w ill be present in Visual Basic 7. While it isn’t clear exactly w hat features w ill be present, you can bet that support for COM+ w ill be at the top of the list.
They c o uld c o ntain the database c alls nec essary to make a withdrawal fro m yo ur savings ac c o unt, register yo u fo r a c o llege c o urse, o r even o rder a bo o k o ver the Internet.
Simply lo o king at a transac tio n fro m a database perspec tive may be a bit to o limiting fo r many applic atio ns. In additio n to manipulating data in the database, transac tio ns o ften perfo rm validatio n alo ng with the database ac tivities. Fo r example, befo re mak-ing a withdrawal fro m yo ur c hec kmak-ing ac c o unt, yo u must first verify that the ac c o unt number is valid, and sec o nd, that there are suffic ient funds in the c hec king ac c o unt befo re subtrac ting the mo ney fro m that ac c o unt.
There are a several ways to implement a transac tio n. The mo st c o mmo n way is to write c o mplex sto red pro c edures that run o n the database server. This appro ac h impo ses extra wo rk o n the database server, whic h may detrac t fro m the database server’s o verall perfo rmanc e. In Windo ws 2000, yo u have the o ptio n o f building COM+ transac tio ns that run under c o ntro l o f a transac tio n server, whic h yo u c an easily run o n a separate mac hine.
The ACID test
Eac h COM+ transac tio n must meet the ACID test. The letters in ACID stand fo r Ato mic ity, Co nsistenc y, Iso latio n, and Durab ility, and serve to identify the differ-ent c riteria that a transac tio n must meet.
Atomicity
Ato micitymeans that either all o r no ne o f a transac tio n is c o mpleted. In o ther wo rds, the wo rk a transac tio n perfo rms c an’t be subdivided. If the transac tio n c o mpletes suc c essfully, all o f the c hanges it makes will remain. If the transac tio n fails, then all o f the c hanges it made must be undo ne.
Co nsider an airline reservatio ns system. When yo u make a reservatio n, yo u spec ify the date, flight number, number o f seats yo u want, plus a number o f parameters suc h as first c lass o r ec o no my. Yo u want the reservatio n to suc c eed o nly if all o f these parameters are met. Otherwise yo u want the reservatio n to fail, so yo u c an try again. Either all o f the seats yo u requested are available o r no ne o f them.
Consistency
Co nsider what happens if the pro c ess fails after the first update is finished, but befo re the sec o nd update is made. The database will auto matic ally ensure that the first update is saved, but it will no t save an inc o mplete update. This means that the mo ney wo uld be remo ved fro m yo ur saving ac c o unt but no t added to yo ur c hec k-ing ac c o unt. Fo r all prac tic al purpo ses, the mo ney wo uld be lo st and the database left in an inc o nsistent state.
By plac ing the two updates into a transac tio n, yo u c an ensure that the database is left in a c o nsistent state. Either bo th updates are c o mpleted o r bo th updates are no t c o mpleted. In this example, whether the transac tio n suc c eeds o r fails, the mo ney wo n’t be lo st.
Isolation
While no t as o bvio us as the previo us c harac teristic s o f a transac tio n, iso latio n is also very impo rtant. Eac h transac tio n lives in its o wn wo rld, where it c an’t see any o f the pro c essing perfo rmed by ano ther ac tive transac tio n. The c o nc ept o f iso latio n is impo rtant bec ause it allo ws the system to rec o ver fro m failures. While the system is ac tively pro c essing transac tio ns, yo u may have do zens o r even hundreds o f ac tive transac tio ns at any po int in time. Ho wever, with transac tio n iso latio n, these transac tio ns c an be viewed as a single stream o f transac tio ns, where o ne transac tio n is c o mpleted befo re the next o ne begins. This pro c ess allo ws rec o very pro -grams to wo rk, and makes it po ssible to implement distributed database systems.
Durability
The last c harac teristic o f a transac tio n is its ability to survive system failures. Onc e a transac tio n has been c o mpleted, it is c ritic al that the c hanges it made aren’t lo st. Fo r this reaso n, it’s impo rtant that the system keep lo gs and bac kups o f all the trans-ac tio ns that were pro c essed. These files make it po ssible fo r wo rk to be rec o vered in c ase o f a c atastro phic system failure.
Class module properties for transactions
In o rder to identify a Visual Basic c lass mo dule as a COM+ transac tio n, yo u need to adjust so me o f its pro perties. These pro perties c o ntro l ho w Visual Basic will c o m-pile yo ur pro gram.
Table 18-1
M TSTransactionM ode Values
Visual Basic Constant COM + Transaction Support Numeric Value
NotAnMTSObject Disabled 0
NoTransactions Not Supported 1
RequiresTransaction Required 2
UsesTransaction Supported 3
RequiresNewTransaction Requires New 4
✦No tAnMTSObje ctimplies that the o b jec t isn’t suppo rted under COM+ Transac tio n Server. Yo u sho uld use this value when yo u do no t expec t to run yo ur c o mpo nent under c o ntro l o f the Transac tio n Server.
✦NoTransactionsmeans that the o bjec t do esn’t suppo rt transac tio ns. When a new instanc e o f the o bjec t is c reated, its o bjec t c o ntext is c reated witho ut a transac tio n.
✦Re quire sTransactionmeans that the c o mpo nent’s o bjec ts must exec ute with-o ut the sc with-o pe with-o f a transac tiwith-o n. When a new instanc e with-o f the with-o bjec t is c reated, the o bjec t c o ntext is inherited fro m the o bjec t c o ntext o f the c lient. If the c lient do esn’t have a transac tio n, a new transac tio n is c reated fo r the o bjec t. If the c lient is a COM+ transac tio n, then a new transac tio n will no t be started bec ause o ne is already ac tive.
✦Use sTransactionmeans that the c o mpo nent’s o bjec ts c an exec ute within the sc o pe o f a transac tio n. When a new instanc e o f the o bjec t is c reated, its o bjec t c o ntext is inherited fro m the o bjec t c o ntext o f the c lient. If the c lient do esn’t have a transac tio n, the new o bjec t will run witho ut a transac tio n.
✦Re quire sNe wTransactionmeans that the c o mpo nent’s o bjec ts must exec ute within their o wn transac tio ns. When a new instanc e o f the o bjec t is c reated, a new transac tio n will auto matic ally be c reated fo r the o bjec t, even if the c alling o bjec t is already exec uting within a transac tio n.
The ObjectContext object
Yo u c an get ac c ess to this o b jec t b y selec ting the COM+ Servic es Type Lib rary fro m the Referenc es windo w b y c ho o sing Pro jec t ÿ Referenc es fro m the Visual Basic main menu ( see Figure 18-5) and then dec laring and c alling the
GetObjectContextfunc tio n, as sho wn b elo w:
Dim MyContext As ObjectContext Set MyContext = GetObjectContext()
Figure 18-5: Selecting the COM+ Services Type Library
ObjectContext object properties
Table 18-2 lists the pro perties o f the ObjectContexto bjec t.
Table 18-2
Properties of the ObjectContext Object
Property Description
ContextInfo An object reference to the ContextInfoobject.
Count A Longvalue containing the num ber of property objects.
Item An object reference to a specific property object.
Security An object reference to the SecurityPropertyobject.
ObjectContext object methods
Function CreateInstance (bstrProgID As String) As Variant
The CreateInstancemetho d returns an o b jec t referenc e to a new instanc e o f the spec ified o b jec t using the c urrent o b jec t’s c o ntext. This func tio n sho uld b e used in plac e o f the CreateObjectfunc tio n, b ec ause it implements the c urrent c o ntext fo r its exec utio n. If the o b jec t isn’t registered with COM+, the o b jec t is merely c reated and no c o ntext will b e assigned. If the o b jec t is registered with COM+, it will b e c reated ac c o rding to the COM+ Transac tio n Suppo rt value and the MTSTransactionModepro perty. bstrProgIDis a Stringvalue c o ntaining the name o f the o b jec t to b e c reated.
Sub DisableCommit( )
The DisableCommitmetho d tells the transac tio n server that the o bjec t’s wo rk has left the system in an inc o nsistent state.
Sub EnableCommit( )
The EnableCommitmetho d tells the transac tio n server that the o bjec t’s wo rk may no t be c o mplete, but that the system is no w in a c o nsistent state.
Function IsCallerInRole(bstrRole As String) As Boolean
The IsCallerInRolemetho d returns Truewhen the o bjec t’s direc t c aller is in the spec ified ro le, either individually o r as part o f a gro up. bstrRoleis a Stringvalue c o ntaining the sec urity ro le.
Function IsInTransaction( ) As Boolean
The IsInTransactionmetho d is Truewhen the o bjec t is exec uting inside a trans-ac tio n.
Function IsSecurityEnabled ( ) As Boolean
The IsSecurityEnabledmetho d is Truewhen sec urity is enabled.
Sub SetAbort( )
The SetAbortmetho d instruc ts the transac tio n server to undo any o f the transac -tio n’s ac -tio ns. This may be bec ause an unrec o verable erro r has o c c urred o r the sys-tem is in an inc o nsistent state.
Sub SetComplete( )
Constructing a COM + Transaction
Co nstruc ting a COM+ transac tio n is fairly easy. Yo u start by c reating an Ac tiveX DLL pro jec t to ho ld the transac tio n. If yo u want to pass any o bjec ts between the trans-ac tio n and the pro gram, yo u will need a sec o nd Ac tiveX DLL to ho ld the type info r-matio n. Finally, to test yo ur transac tio n, yo u’ll need a simple applic atio n that c alls the transac tio n.
Fo r this example, I’m go ing to use the Custo mers tab le and c reate COM+ transac -tio ns to retrieve a single c usto mer and to update a single c usto mer. The info rma-tio n will b e passed b ac k and fo rth b etween the c lient and the transac rma-tio n server using the Custo mer o b jec t. To demo nstrate the transac tio ns, I’m also go ing to b uild a simple IIS Applic atio n and run it thro ugh the IIS Web server.
Holding type information
One pro blem yo u will enc o unter when yo u begin using COM+ transac tio ns is that yo u c an’t rely o n glo bal variables to pass info rmatio n bac k and fo rth to the ro utines yo u may c all. Everything must be passed as a parameter. Depending o n the data yo u want to share with a ro utine, this c an be a pro blem.
Using Visual Basic ’s c lass mo dules, yo u c an c reate an o bjec t that c o ntains a lo t o f info rmatio n in a single entity. When using so me o f the mo re advanc ed features in Windo ws, suc h as COM+ transac tio ns and message queuing, this is my favo rite way to pass info rmatio n aro und.
The do wnside to using c lass mo dules to pass info rmatio n aro und in a COM+ ac tio n is that yo u really have to deal with two different pro grams. The COM+ trans-ac tio n o perates independently o f the applic atio n pro gram using the transtrans-ac tio n. Therefo re, bo th pro grams need a c o py o f the definitio ns. The o nly reaso nable way to handle this situatio n is to intro duc e a third c o de mo dule that ho lds the type defi-nitio ns fo r yo ur transac tio ns. This third mo dule exists o n bo th the c lient mac hine and the transac tio n server mac hine.
Creating storage for property values
Listing 18-1:
The module level declarations in Customer
Option Explicit
Private XCustomerID As Long Private XName As String Private XStreet As String Private XCity As String Private XState As String Private XZip As Long Private XPhone As String
Private XEMailAddress As String Private XDateAdded As Date Private XDateUpdated As Date Private XMailingList As Boolean Private XComments As String Private XIsDirty As Boolean
Yo u sho uld no te that in additio n to the vario us fields fro m the database, I also added o ne mo re value, c alled XIsDirty. The XIsDirtypro perty is used to indic ate when the data in the o bjec t has been c hanged. It’s a quic k and easy way to deter-mine if the info rmatio n was c hanged and the database sho uld be updated.
M anaging property values
The Property Getro utine just returns the value o f the c o rrespo nding Xvariable ( see Listing 18-2) , while the Property Letro utine is a little mo re c o mplic ated ( see Listing 18-3) .
The Property Letro utine determines if the value o f the pro perty is different than the value already in private sto rage. If the value is different, then I save the new value, set the XIsDirtypro perty, and mark the pro perty as c hanged. Otherwise, I igno re the assignment. While c hec king the assignment is a little extra wo rk, it allo ws so me-o ne tme-o reassign the c urrent value tme-o the prme-o perty withme-o ut resetting the XIsDirtyflag.
Listing 18-2:
The CustomerId Property Get
routine in Customer
Public Property Get CustomerId() As Long
CustomerId = XCustomerID
Listing 18-3:
The CustomerId Property Let
routine in Customer
Public Property Let CustomerId(c As Long)
If c <> XCustomerID Then XCustomerID = c XIsDirty = True
PropertyChanged “CustomerId”
End If
End Property
Property M ay I: The CanPropertyChangem ethod isn’t required w hen dealing w ith properties in the Customerobject, since the Customerobject can’t act as a data consum er.
Initializing property values
I c ho se to make the Custo mers o bjec t a persistable o bjec t. This will have a big ben-efit later when I talk abo ut message queuing in Chapter 19. Ho wever, fo r no rmal COM+ transac tio ns, yo u do n’t really need persistent o bjec ts. Onc e the o bjec t is instantiated, it will remain instantiated until yo u destro y it.
Listing 18-4 c o ntains the statements nec essary to initialize the variables in lo c al sto rage. No te that I just use reaso nable default values fo r all o f these pro perties exc ept fo r XDateAddedand XDateUpdated. Fo r these values, I use the func tio n Now to save the c urrent date and time into these variables. This makes it easier fo r so meo ne to c reate a new Custo mer o bjec t and no t wo rry abo ut assigning values to these two fields. It also wo n’t c ause a pro blem when the COM+ transac tio n returns info rmatio n fro m the database, sinc e these initial values will be o verlaid with the live values fro m the database.
Listing 18-4:
The Class_InitProperties event in Customer
Private Sub Class_InitProperties()
XCustomerID = -1 XName = “” XStreet = “” XCity = “” XState = “”
XZip = 0 XPhone = “”
XEMailAddress = “” XDateAdded = Now XDateUpdated = Now XMailingList = False XComments = “” XIsDirty = False
End Sub
As yo u wo uld expec t, the ReadPropertiesand WritePropertiesevents are pretty simple, just a series o f statement that use the ReadPropertyand WriteProperty metho ds to resto re and save these values. Listing 18-5 sho ws the ReadProperties event.
Listing 18-5:
The Class_ReadProperties event in Customer
Private Sub Class_ReadProperties(PropBag As PropertyBag)
XCustomerID = PropBag.ReadProperty(“CustomerId”, 0) XName = PropBag.ReadProperty(“Name”, “”)
XStreet = PropBag.ReadProperty(“Street”, “”) XCity = PropBag.ReadProperty(“City”, “”) XState = PropBag.ReadProperty(“State”, “”) XZip = PropBag.ReadProperty(“Zip”, 0) XPhone = PropBag.ReadProperty(“Phone”, “”)
XEMailAddress = PropBag.ReadProperty(“EMailAddress”, “”) XDateAdded = PropBag.ReadProperty(“DateAdded”, 0)
XDateUpdated = PropBag.ReadProperty(“DateUpdated”, 0) XMailingList = PropBag.ReadProperty(“MailingList”, False) XComments = PropBag.ReadProperty(“Comments”, “”)
XIsDirty = False
End Sub
Installing the DLL
Onc e yo u build yo ur pro gram, yo u need to c o mpile it to an Ac tiveX DLL ( Dynamic Linking Library) and then register it in the Windo ws Registry. When yo u register yo ur DLL, selec ted info rmatio n abo ut the DLL will be lo aded into the Registry, inc luding the lo c atio n o f the DLL file, the name o f the o bjec ts available, and the Glo bally Unique Identifiers ( GUID) that are used to lo c ate them.
When yo ur pro gram referenc es an o bjec t, it presents the o bjec t’s GUID to Windo ws, whic h in turn uses it as a key to lo c ate info rmatio n abo ut the o bjec t in the Registry. This means that the ac tual lo c atio n o f the file c an be independent o f the applic atio n.
To register yo ur file, yo u need to use the RegSvr32 utility pro gram. To run it, c ho o se Start ➪Run fro m the Windo ws taskbar. Then enter the RegSvr32fo llo wed by the fully qualified path name to the DLL file, as sho wn belo w:
RegSvr32 d:\VB6DB\Chapter18\CustomerObjects\cust.dll
and press Enter. The registratio n pro gram will run fo r a split sec o nd and display a message bo x saying that RegisterDLL Server suc c eeded.
If yo u need to make a c hange to the DLL after yo u have registered it, yo u must run the fo llo wing c o mmand:
RegSvr32 /u d:\VB6DB\Chapter18\CustomerObjects\cust.dll
It will ac kno wledge the request by saying DLLUnregister Server suc c eeded.
DOS ain’t dead: After using DOS and m any other character operating system s over the years, I actually like typing m y com m ands and seeing the results. I often use DOS to display directory inform ation and to copy files, and as a result, I usu-ally have a DOS w indow open. So rather than choosing Start➪Run, I usually just toggle to m y DOS w indow to run the RegSvr32 com m and. Besides, if the DLL is in the current directory, I need only type the file nam e rather than the fully qualified path nam e.
Accessing the database with transactions
No w that I have an o bjec t I c an pass bac k and fo rth to COM+ transac tio ns, I want to build so me transac tio ns. Fo r all prac tic al purpo ses, building a COM+ transac tio n is just like building any o ther COM c o mpo nent that ac c esses a database — with two exc eptio ns. First, yo u need to use the ObjectContexto bjec t to info rm the transac -tio n server o f the transac -tio n’s status. Sec o nd, yo u need to grab and release database reso urc es, suc h as the Co nnec tio n o bjec t, quic kly.
Getting customer information
The GetCustomermetho d ( see Listing 18-6) retrieves the c usto mer info rmatio n fo r the c usto mer spec ified in the CustomerIdparameter and returns it to the c alling pro gram using the Custo mer o bjec t. While a metho d that stric tly reads info rmatio n fro m the database do esn’t benefit fro m the COM+ transac tio n server’s ability to manage c o mplex transac tio ns, it do es allo w this ro utine to o perate mo re effic iently than it wo uld if yo u embedded the c o de direc tly in yo ur applic atio n pro gram.
Listing 18-6:
The GetCustomer method of CustomerInfo
Public Function GetCustomer(CustomerId As Long) As Customer
Dim c As Customer
cmd.CommandText = “Select * from Customers “ & _ “Where CustomerId = ?”
Set parm = cmd.CreateParameter(“CustomerId”, adInteger, _ adParamInput, 4) “Can’t retrieve the “ & _
“record for CustomerId “ & _
FormatNumber(CustomerId, 0) & “. Error: “ & _ Err.Description & “-” & _
Hex(Err.Number)
Listing 18-6
(continued)
Set c = Nothing
Else
Set c = New Customer
c.CustomerId = rs.Fields(“CustomerId”) c.Name = rs.Fields(“Name”)
c.Street = rs.Fields(“Street”) c.City = rs.Fields(“City”) c.State = rs.Fields(“State”) c.Zip = rs.Fields(“Zip”) c.Phone = rs.Fields(“Phone”)
c.EMailAddress = rs.Fields(“EMailAddress”) c.DateAdded = rs.Fields(“DateAdded”) c.DateUpdated = rs.Fields(“DateUpdated”) c.MailingList = rs.Fields(“MailingList”) c.Comments = rs.Fields(“Comments”)
End If
Set GetCustomer = c rs.Close
db.Close
Set rs = Nothing Set db = Nothing Set c = Nothing Set o = Nothing
End Function
The GetCustomermetho d begins by dec laring a number o f o bjec ts that I’ll use in this pro gram. Next, I’ll get an o bjec t referenc e to the ObjectContextfo r this trans-ac tio n. While I do n’t really need it, it isn’t a bad idea to get in the habit o f starting every metho d by getting the c o ntext.
After the c o nnec tio n is o pened, I c reate a Commando bjec t with a parameterized
Se le ctstatement and its asso c iated Parametero bjec t. I c ho se to use the Command o bjec t rather than a Recordsetbec ause the Commando bjec t will be mo re effic ient in the lo ng run. SQL Server 7 will parse the query the first time it sees it, and the next time I use the query, it will be able to use the already parsed versio n. This makes it nearly as fast as a sto red pro c edure, witho ut the headac hes o f c reating a sto red pro c edure.
When I exec ute the Command, it will return a Recordseto b jec t c o ntaining the value I req uested, in whic h c ase I’ll save the values into a Customero b jec t and return it as the value o f the func tio n. If exec uting the Commandgenerated an erro r, I’ll write the erro r to the applic atio n’s lo g file and return Nothingas the value o f the func tio n.
At the end o f the func tio n, I c lo se the Recordsetand Connectiono bjec ts and destro y all o f the o bjec ts I used in the ro utine. No te that I destro y the ObjectContexto bjec t, sinc e it is no lo nger nec essary. A c all to SetCompleteo r SetAbortisn’t nec essary sinc e I didn’t mo dify any data.
Saving customer information
The PutCustomermetho d sho wn in Listing 18-7 fo llo ws the same basic lo gic flo w as the GetCustomermetho d yo u saw in 18-6. I begin by ac quiring a c o nnec tio n to the database. Then I c reate a Commando bjec t that exec utes an SQL Update state-ment. Next I assign the appro priate values fro m the Customero bjec t to the parame-ters in the c o mmand and then exec ute the Updatestatement. Finally, I return any erro r info rmatio n as the value o f the func tio n, signal the ObjectContextthat the transac tio n is c o mplete and destro y the o bjec ts I used.
Listing 18-7:
The PutCustomer method of CustomerInfo
Public Function PutCustomer(c As Customer) As Long
On Error Resume Next
Dim cmd As ADODB.Command Dim db As ADODB.Connection Dim o As ObjectContext Dim parm As ADODB.Parameter
Set o = GetObjectContext()
PutCustomer = 0 Err.Clear
Listing 18-7
(continued)
Set db = New ADODB.Connection db.Provider = “sqloledb” db.ConnectionString = “Athena” db.CursorLocation = adUseNone db.Open , “sa”, “”
db.DefaultDatabase = “VB6DB”
Set cmd = New ADODB.Command Set cmd.ActiveConnection = db
cmd.CommandText = “Update Customers Set Name=?, Street=?, “ _ “City=?, State=?, “ & _
“Zip=?, Phone=?, EMailAddress=?, DateAdded=?, “ & _ “DateUpdated=?, MailingList=?, Comments=? “ & _ “Where CustomerId=?”
Set parm = cmd.CreateParameter(“Name”, adVarChar, _ adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Street”, adVarChar, _ adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“City”, adVarChar, _ adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“State”, adChar, _ adParamInput, 2)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Zip”, adInteger, _ adParamInput, 4)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Phone”, adVarChar, _ adParamInput, 32)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“EMailAddress”, adVarChar, _ adParamInput, 128)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“DateAdded”, adDBDate, _ adParamInput)
Set parm = cmd.CreateParameter(“DateUpdated”, adDBDate, _ adParamInput)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“MailingList”, adBoolean, _ adParamInput)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Comments”, adVarChar, _ adParamInput, 256)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“CustomerId”, adInteger, _ adParamInput, 4)
“Customer(PutCustomer): Can’t update the record “ & _ “for CustomerId “ & _
Yo u may be wo ndering why I c ho se to use the Updatestatement, rather than update the database using a Recordseto bjec t. The answer is really simple: the
Updatestatement is mo re effic ient in this situatio n. In o rder to use a Recordset, yo u wo uld have to retrieve the rec o rds a sec o nd time. Then yo u wo uld have to c hange the values in the c urrent rec o rd and use the Updatemetho d to send the c hanges bac k to the database. In this c ase, simply send the update direc tly to the server.
Installing the transaction into COM +
The COM+ transac tio n server is managed by using the Co mpo nent Servic es utility. Yo u c an ac c ess this utility by c ho o sing Start➪Pro grams➪Administrative To o ls➪
Co mpo nent Servic es ( see Figure 18-4) .
To add yo ur applic atio n to the COM+ transac tio n server, yo u need to perfo rm these steps:
1.Cho o se Start➪Pro grams➪Administrative To o ls➪Co mpo nent Servic es fro m the Windo ws taskbar.
2.Under Co nso le Ro o t, o pen COM+ Applic atio ns by selec ting Co mpo nent Servic es, then Co mputers and the name o f the c o mputer o n whic h yo u want to c reate servic e.
3.Right c lic k o n Co mpo nent Servic es and c ho o se New➪Applic atio n fro m the po p-up menu. This starts the COM Applic atio n Install Wizard.
4.Press Next fro m the welc o me sc reen and then c lic k o n the Create an empty applic atio n butto n.
5.On the Create Empty Applic atio n windo w, enter the name fo r yo ur new appli-c atio n and appli-c ho o se Server Appliappli-c atio n ( see Figure 18-6) .
6.Clic k Next to display the Set Applic atio n Identity windo w sho wn in Figure 18-7. Cho o se the user ac c o unt under whic h the applic atio n will run. Yo u c an c ho o se to use the sec urity o f the user name who is lo gged o nto the server’s c o nso le (the interac tive user) when the applic atio n is run. Yo u may also enter the name and passwo rd o f a spec ific user. Clic k Next to go to the last step o f the wizard.
7.Clic k Finish to install the empty applic atio n.
Figure 18-6: Entering the nam e of the application
Figure 18-7: Associating the application w ith a user nam e
Onc e yo u have an empty applic atio n, yo u need to impo rt yo ur Ac tiveX DLL using these steps in the Co mpo nent Servic es utility ( c ho o se Start➪Pro grams➪
Administrative To o ls➪Co mpo nent Servic es in Windo ws 2000) .
1.Expand the applic atio n yo u just c reated to display the Co mpo nents and Ro les fo lders beneath it.
3.Clic k Next to mo ve to the Impo rt o r Install a Co mpo nent step and c lic k o n Install New Co mpo nent( s) butto n.
4.A File Open dialo g bo x will be displayed. Cho o se the name o f the DLL file yo u just c reated and c lic k o n the Open butto n to display the Install New Co mpo nents dialo g bo x with the file yo u just selec ted (see Figure 18-8). If yo u need to install mo re than o ne file, press the Add butto n.
5.After yo u have selec ted the files to be installed, c lic k Next to go to the last step o f the wizard and press Finish to add the c o mpo nent to the applic atio n.
Figure 18-8: Selecting the nam e of your ActiveX DLL
Building a simple test program
In o rder to test the COM+ transac tio ns, I c reated simple IIS Applic atio n. This pro -gram respo nds to the URL http://Athena/VB6DB18/VB6DB18.ASPwith a Web page, as sho wn in Figure 18-9.
IIS Applications are neat: My favorite feature in Visual Basic 6 is the ability to cre-ate a com piled, Web server-based application using IIS Applications. IIS Applications are generally m ore efficient than ASP applications and they are m ore secure because the source code is separate from the executable program .
When so meo ne enters the URL to run the IIS Applic atio n, IIS will trigger the WebClass_Startevent sho wn in Listing 18-8. Depending o n the request, o ne o f three things will happen. If no fo rm info rmatio n is inc luded, a blank Web fo rm will be displayed, with default values fo r the Customero bjec t. If a GetCustomerrequest is made, then the CustomerIdvalue fro m the fo rm will be passed to the GetCustomer transac tio n to retrieve the spec ified c usto mer. If a PutCustomerrequest is made, then the info rmatio n o n the fo rm will be passed to the PutCustomermetho d to update the database. A fo rm with the info rmatio n abo ut the c urrent c usto mer is returned in bo th the PutCustomerand GetCustomerrequests.
Figure 18-9: View ing address inform ation returned by the COM+ transaction
Listing 18-8:
The WebClass_Start event in Address
Information
Private Sub WebClass_Start()
Dim c As Cust.Customer Dim ci As Object
If Len(Request.Form(“GetCustomer”)) > 0 Then Set ci = CreateObject(“CustInfo.CustomerInfo”)
Set c = ci.GetCustomer(CLng(Request.Form(“CustomerId”))) Set ci = Nothing
ElseIf Len(Request.Form(“PutCustomer”)) > 0 Then Set ci = CreateObject(“CustInfo.CustomerInfo”) Set c = New Cust.Customer
c.CustomerId = Request.Form(“CustomerId”) c.Name = Request.Form(“Name”)
c.Street = Request.Form(“Street”) c.City = Request.Form(“City”) c.State = Request.Form(“State”) c.Zip = Request.Form(“Zip”)
Listing 18-8
(continued)
.Write “</tr>” .Write “<tr>”
.Write “<td>City/State/Zip:</td>” .Write “<td>”
.Write “<input type=””text”” name=””City””” .Write “ size=””30”” value=””” & c.City & “””>” .Write “<input type=””text”” name=””State””” .Write “ size=””2”” value=””” & c.State & “””>” .Write “<input type=””text”” name=””Zip””” .Write “ size=””5”” value=”
Listing 18-8
(continued)
.Write “</table>”
.Write “<input type=””submit”” value=””Get Customer”” “ .Write “name=””GetCustomer””>”
.Write “<input type=””submit”” value=””Update Customer”” “ .Write “name=””PutCustomer””>”
.Write “<input type=””reset”” value=””Reset”” .Write “ name=””Reset””>”
.Write “</form>” .Write “</body>” .Write “</html>” End With
Set c = Nothing
End Sub
This pro gram is a little tric ky in the way it wo rks. It relies o n the fac t that the Request.Formmetho d do esn’t return an erro r when I try to ac c ess a partic ular field that isn’t present, plus the fac t that the value o f a butto n is present in the fo rm data o nly when it is pressed. So I c an c hec k Request.Form(“GetCustomer”)to see if so meo ne pressed the Get Custo mer butto n and kno w that the value will o nly be there when so meo ne pressed that butto n.
This means that I c an use a c o mpo und Ifstatement to determine whic h o f the but-to ns o n the fo rm were pressed, if any. If the user pressed the Get Cusbut-to mer butbut-to n, I c an c reate an instanc e o f the CustomerInfoo bjec t and c all the GetCustomermetho d to return the spec ified c usto mer value. Likewise, I c an c reate a CustomerInfoo bjec t to c all the PutCustomermetho d if I find the Put Custo mer butto n in the Form. Requestmetho d.
If neither butto n o n the fo rm was pressed, I c an simply c reate an empty Customer o bjec t. This means that no matter ho w I start the fo rm, I’ll have a valid Customer o bjec t to use when I generate the fo rm.
The sec o nd half o f the ro utine is devo ted to c reating the HTML tags nec essary to display the fo rm. I embedded the referenc es to the Customero bjec t where nec es-sary to display info rmatio n o n the fo rm.
Developing IIS Application forms the lazy way: I used Microsoft FrontPage 2000 to create the basic form and then I copied the HTM L tags in WordPad and added the appropriate calls to Write. Finally, I copied the statem ents into Visual Basic and added the code to reference the various objects I created.
Tho ughts o n COM+The COM+ Transac tio n Server isn’t appro priate fo r all applic a-tio ns. While COM+ transac a-tio ns help large applic aa-tio ns, they may ac tually hurt small o nes. First, it adds ano ther level o f c o mplexity that isn’t nec essary in a small applic atio n. Sec o nd, it may ac tually perfo rm slo wer, depending o n the hardware c o nfiguratio n.
Ho wever, there is no substitute fo r COM+ if yo u are building a high-vo lume applic a-tio n. This is espec ially true if yo u suppo rt multiple user interfac es to the data, suc h as a traditio nal Visual Basic fo rm-based c lient/ server pro gram and a Web based applic atio n using an IIS Applic atio n.
There is a flaw in the update lo gic o f the sample applic atio n. Yo u may run into a c o nflic t when multiple users try to update the data. Co nsider the c ase where Christo pher gets a c o py o f the data, then Samantha gets a c o py o f the data and updates it, and then Christo pher perfo rms his update. Samantha’s update wo uld be lo st and Christo pher wo uld no t have seen her c hanges. Fo r many applic atio ns this appro ac h is fine, but it may c ause a pro blem with o thers.
This pro blem is similar to the pro blem with o ptimistic lo c ks, and yo u c an use a sim-ilar appro ac h to c o rrec t it. Yo u c o uld mo dify the Customero bjec t to sto re bo th the o riginal values fo r eac h field and the c urrent values fo r eac h field. Then, when yo u update the database, yo u c an c o mpare the o riginal values to the values in the database and abo rt the transac tio n if there is a differenc e.
Summary
In this c hapter yo u learned the fo llo wing:
✦Yo u c an build applic atio ns by using multiple tiers o f pro c essing. This is kno wn as n-tier pro c essing.
✦Yo u c an use transac tio n servers to impro ve the perfo rmanc e o f yo ur applic atio n.
✦Yo u c an use the Co mpo nent Servic es utility to add transac tio ns to a COM+ Transac tio n Server.
✦Yo u c an use the ACID test to determine if yo u have a valid transac tio n.
✦Yo u c an use the ObjectContexto bjec t to c o mmunic ate fro m yo ur transac -tio n to the transac -tio n server.
✦Yo u c an c o ntro l sec urity o n a transac tio n so that it c an perfo rm tasks with the autho rity o f so meo ne o ther than the user name that c alled the transac tio n.