|
An important addition in Active Server Pages 2.0 is the ability to create
a transactional
script: one whose constituent code segments all succeed completely or
fail
as a group. For example, using such a script, one section of code could
remove a
record from an inventory table, and a second section could add a record
to a sales
log table. However, only if both sections of code succeed does the script
itself
succeed. If the removal of the inventory record or the addition of the
sales record
fails, the script itself fails. Both processes are rolled back: the deleted
record, if it
was removed, is added back into the database, and the sales record, if
it was
added, is removed from the sales log table. This ability to wrap several
functions
in a single transactional unit that succeeds or fails as a whole is an
important
improvement in the power of ASP applications. Previously, all transactions
relied
on database transaction support.
ASP application transactions are controlled by Microsoft Transaction Server.
This
piece of the BackOffice suite allows control over all database actions
coded to use
MTS. Support for MTS and transactional scripts is built into IIS and Personal
Web
Server and does not require any special setup. Without MTS transactional
support,
your applications would have to track all database changes manually and
roll back
all database actions by hand, keeping track of multiuser and concurrency
issues,
etc. MTS gives this support for very little extra codingas long
as the database
your application is connected to supports the XA protocol from the X/Open
consortium. Note that this support is currently limited to SQL Server.
Note, also,
that this means that file actions are not yet supported by MTSor
at least, not
automatically.
ASPs support of MTS transactions is coded through the use of the
ObjectContext
object, which represents the actual ObjectContext object of MTS itself.
By calling
methods of the ObjectContext object and coding its events, you can create
a transactional
script with only a few more lines of code.
To declare all the script on a given page to be transactional, simply
add the
following line of code as the first line in your script:
<%@ TRANSACTION = Required %>
For more details on the TRANSACTION ASP directive, see Chapter 10, Preprocessing
Directives, Server-Side Includes, and GLOBAL.ASA. Here it is important
only
that this line be the first in your script; including this line alerts
the web server to
use MTS to ensure that the script succeeds or fails as a whole.
To commit the transaction or abort it, you simply call the SetComplete
or SetAbort
methods of the ObjectContext object, respectively. If you are dealing
with a
complex transaction containing segments of code that are not supported
by MTS
(notably file actions), you can specially code for these actions in the
ObjectContext
events OnTransactionCommit and OnTransactionAbort. There are examples
of
all of these methods and event procedures in the reference section later
in this
chapter.
Comments/Troubleshooting
There are currently two very important limitations in constructing transactional
scripts:
Only database actions are supported, and only databases that support
the XA
protocol are supported by MTS.
A transaction cannot span more than one ASP page. For this reason,
you must
be very careful in creating your pages: they must include all the actions
required by your transactions but not be so large as to slow the processing
of
the page by too large a percentage.
If you write your own server components that complete some or all of the
database
actions in your transaction, that component must be registered in an MTS
ObjectContext Object Summary
Properties
None
Collections
None
Methods
SetComplete
SetAbort
Events
OnTransactionCommit
OnTransactionAbort
* MTS transactional support is provided only if the component is registered.
Whats more, you should create your own library packages and not
include
your component in the IIS in-process package. Custom library packages
can be
used by multiple ASP applications and are run in the same process as the
ASP
DLL. Setting up library packages also gives your component the ability
to be
pooled for reuse by your applications. This pooling is managed by MTS
as well.
You also can add your components to a server package, but doing so is
required
only for role-based transactions or transactions running on remote computers.
Note that you should not give objects functioning in transactions session-
or application-
level scope, since transactional objects are deactivated at the end of
their
transaction. If you do give such an object session or application scope,
calls after
the end of the transaction will fail and raise an error.
Although transactions are supported only for database actions, you can
add code
to the OnTransactionCommit and OnTransactionAbort event procedures to
provide
your own nondatabase transactional support. For example, code in these
event
procedures could easily be used to write or remove files from the file
system upon
success or failure of a given transaction.
ObjectContext exposes six methods other than the ones you can access through
ASP. However, these are accessible only through code within the server
components
being managed by MTS.
Transactional scripts are a very important addition to ASP. If you had
access to
database transactions only through use of ActiveX Data Objects, it would
still be a
very important and useful function. However, by creating custom server
components,
you can create complex and powerful transactions.
Methods Reference
SetAbort
ObjectContext.SetAbort
Aborts the transaction as a whole. When it is called, the transaction
ends unsuccessfully,
regardless of code that has or has not already been processed in your
script.
You can use this method in your script after testing for the completion
of a given
part of the transaction, or a server component managed by MTS can call
it. Calling
SetAbort rolls back any parts of the transaction that have already occurred
and
calls the ObjectContext_OnTransactionAbort event procedure if one exists
in your
script.
Parameters
None
* For more information on MTS packages and server components,
see the forthcoming book,
Developing ASP Components, written by Shelley Powers and published by
OReilly & Associates.
Example
<%
' The following code tests the result from a method call
' to a custom server component that attempts to remove
' a book from the inventory table and then tests the
' results from a credit card check.
' Based on this code and the segment that follows it, the
' script will call either the SetAbort or the SetComplete
' method of the ObjectContext object.
' Attempt to sell 2 copies of the book Animal Farm.
intBooks = MyInventory.SellBook("Animal Farm", 2)
' Check the credit card given by the client.
intCheckCC = MyCreditChecker.ChkCard("0001231234")
If intBooks = 2 And intCheckCC = 0 Then
' Complete the transaction. Two copies of the book
' are in the inventory and the credit card checks out.
ObjectContext.SetComplete
Else
' Abort the transaction. Either there are not two
' copies of the book in the inventory or the credit
' card did not check out.
ObjectContext.SetAbort
End If
%>
Notes
Any segment of a transactional script can call the SetAbort method. Note
that if
you have code that exists after the call to SetAbort, it will not be processed
until
after the execution of the OnTransactionAbort event procedure, if one
exists. For
this reason, be sure that your OnTransactionAbort event procedure performs
any
cleanup that is necessary for actions that are not supported in an MTS
transaction
(notably file actions).
If you want some code to be processed regardless of a call to SetAbort,
make sure
that it is before the call to SetAbort in the script, or test for completion
of the transaction
after your code in the script.
SetComplete
ObjectContext.SetComplete
Signals the successful completion of a transaction. When it is called,
the code in
the OnTransactionCommit event procedure code is processed if it exists.
A call to the SetComplete method from within the script itself only indicates
the
success of the script on the page. It does not override possible failure
of the code
within the components referenced in the script. All transactional components
in
the script must signal SetComplete for the transaction to commit.
Parameters
None
Example
See the example in the previous section, SetAbort.
Notes
Note that calling SetComplete does not necessarily mean that the entire
transaction
is complete. Every component called from the script also must call the
SetComplete method of the ObjectContext object.
If you do not explicitly call SetComplete, the transaction is complete
only after all
code is processed without any calls to SetAbort. If no call to SetAbort
is made by
the end of the script, the OnTransactionCommit event procedure code is
processed if it exists, regardless of whether SetComplete is called.
Events Reference
OnTransactionAbort
OnTransactionAbort( )
The OnTransactionAbort event procedure is processed immediately if the
SetAbort
method of the ObjectContext object is called explicitly in scripted code
or by a
server component called from the scripted code. If no code calls the SetAbort
method, this event procedure is never processed.
Parameters
None
Example
<%
' The following code procedure is processed when the code in
' the SetAbort method example is processed.
SubOnTransactionAbort ()
%>
Your book sales transaction could not be completed.
Either there was not sufficient inventory for your
sale to be processed, or your credit card did not
go through.
<%
' Clean up any nontransactional actions here...
End Sub
%>
Notes
Use OnTransactionAbort to clean up any nonsupported actions your transaction
makes that must be reversed if the transaction fails. This includes changes
to variables
(session- and application-level scope), the registry, and the file system.
Note,
however, that your server components should clean up after themselves.
You also should use the OnTransactionAbort event to inform the client
that the
transaction has failed.
Do not call the SetAbort or SetCommit methods from the OnTransactionAbort
event procedure. Doing so may introduce a loop and result in the loss
of function
for your application and/or a loss of data.
OnTransactionCommit
OnTransactionCommit()
The OnTransactionCommit event procedure is processed immediately if the
SetComplete method of the ObjectContext object is called explicitly in
scripted
code or by a server component called from the scripted code. It also is
called
implicitly if no script on the current page called the SetAbort method.
Parameters
None
Example
<%
' The following code procedure is processed when the code in
' the SetAbort method example is processed.
SubOnTransactionCommit ()
%>
Your book sales transaction was completed.
Thank you for your sale.
<%
Session("intTotalSales") = Session("intTotalSales")
+ 1
' Process any nontransactional code here...
End Sub
%>
Notes
The OnTransactionCommit event procedure can be used to inform the client
of the
success of the transaction. It also can be used for code that you want
to be
processed only if the transaction completes successfully.
Do not call the SetAbort or SetCommit methods from the OnTransactionCommit
event procedure. Doing so may introduce a loop and result in the loss
of function
for your application and/or a loss of data.
|