Creating Transactional Scripts

Frequently business applications need to the ability to run scripts and components within transactions. A transaction is a server operation that succeeds or fails as a whole, even if the operation involves many steps (for example, ordering, checking inventory, and billing). You can create ASP scripts that run within a transaction so that if any portion of the script fails, the entire transaction is aborted.

ASP transaction processing is based on Microsoft® Transaction Server (MTS), a transaction processing system for developing, deploying, and managing high performance, scalable, and robust enterprise, Internet, and intranet server applications. Transaction Server defines an application programming model for developing distributed, component-based applications. It also provides a run-time environment for deploying and managing these applications.

The functionality required to create transactional scripts is built into Internet Information Server and Personal Web Server. If you install Microsoft Transaction Server, you can also package components so they run within transactions.

About Transactions>

A transaction is an operation that succeeds or fails as a whole. Transaction processing is used to update databases reliably. When you are making many related changes to a database or updating several databases at once, you want to ensure that all of the changes are correctly executed. If any of the changes fail, you want to restore the original state of the database tables.

Without MTS, you would have to write your scripts and components to manually track the requested changes and restore data if any changes failed. With MTS, you simply declare your scripts and components to require transactions and let MTS handle the transaction coordination. Transaction processing applies only to database access; MTS cannot roll back changes to the file system or changes to other, nontransactional resources. The database your application accesses must be supported by MTS. Currently MTS supports SQL Server and any database that supports the XA protocol from the X/Open consortium. MTS will continue to expand its support for other databases.

A transaction cannot span multiple ASP pages. If a transaction requires objects from several transactional components, you should group operations that use those objects into one ASP page. For example, suppose you have a component that updates a payroll database and a component that updates employee records in a human resources database. To record new salary information for an employee, you might want to write a script that calls both components under one transaction context to update the payroll database and to update the employee's grade or level in the human resources database.

Declaring a Transactional Script

When you declare a page to be transactional, any script commands and objects used on the page are run under the same transaction context. Transaction Server handles the details of creating the transaction and determining whether the transaction succeeds (commits) or fails (aborts). To declare a page transactional, add the @TRANSACTION directive to the top of the page:

<%@ TRANSACTION = value %>

The value argument can be one of the following:

Value Meaning
Requires_New Starts a new transaction.
Required Starts a new transaction.
Supported Does not start a transaction.
Not_Supported Does not start a transaction.

The @TRANSACTION directive must be the very first line on the page, otherwise an error is generated. You must add the directive to each page that should be run under a transaction. The current transaction ends when the script finishes processing.

Most applications only require transaction context for certain operations. For example, an airline site might use transactional scripts for ticket purchasing and seat assignments. All other scripts could be safely run without a transaction context. Because transactions should be used only for pages that need transaction processing, you cannot declare an application's Global.asa file as transactional.

If a transaction is aborted, Transaction Server rolls back any changes made to resources that support transactions. Currently, only database servers fully support transactions as this data is the most critical to enterprise applications. Transaction Server does not roll back changes to files on a hard disk, ASP session and application variables, and collections. You can, however, write scripts that restore variables and collections by writing transaction events, as described later in this topic. Your script can also explicitly commit or abort a transaction if an operation such as writing data to a file fails.

Committing or Aborting a Script

Because Transaction Server tracks transaction processing, it determines whether a transaction has completed successfully or failed. A script can explicitly declare that is aborting a transaction by calling ObjectContext.SetAbort. For example, your script might abort a transaction if it receives an error from a component, if a business rule is violated (for example, if the account balance falls below 0), or if a nontransactional operation, such as reading from or writing to a file, fails. The transaction is also aborted if the page times out before the transaction is completed.

Writing Transaction Events

A script itself cannot determine whether a transaction has succeeded or failed. However, you can write events that are called when the transaction commits or aborts. For example, suppose you have a script that credits a bank account, and you want to return different pages to the user depending on the status of the transaction. You can use the OnTransactionCommit and OnTransactionAbort events to write different responses to the user.

<%@ TRANSACTION = Required %>

<%
'Buffer output so that different pages can be displayed.
Response.Buffer = True
%>

<HTML>
<BODY>
<H1>Welcome to the online banking service</H1>


<%
Set BankAction = Server.CreateObject("MyExample.BankComponent")
BankAction.Deposit(Request("AcctNum"))
%>

<P>Thank you.  Your transaction is being processed.</P>
</BODY>
</HTML>

<%
' Display this page if the transaction succeeds.
Sub OnTransactionCommit()
  Response.Write "<HTML>"
  Response.Write "<BODY>"
  Response.Write "Thank you.  Your account has been credited."
  Response.Write "</BODY>"
  Response.Write "</HTML>"
  Response.Flush()
end sub
%>

<%
' Display this page if the transaction fails.
Sub OnTransactionAbort()
  Response.Clear()
  Response.Write "<HTML>"
  Response.Write "<BODY>"
  Response.Write "We are unable to complete your transaction."
  Response.Write "</BODY>"
  Response.Write "</HTML>"
  Response.Flush()
End sub
%>

Registering a Component in MTS Explorer

To participate in a transaction, a component must be registered in an MTS package and must be configured to require a transaction. For example, if your script processes orders by calling a component that updates an inventory database and a component that updates a payment database, you would want both components to run under a transaction context. Transaction Server ensures that if either component fails, the entire order is rolled back and neither database is updated. Some components do not require transactions; for example, the Ad Rotator component has no need of transactions.

You use MTS Explorer to register and configure a transactional component. You must set the transaction attribute to either Requires a Transaction or Requires a New Transaction. Components must be registered in an MTS package. Do not put your components in the IIS in-process package; instead, create your own package. Generally, you should put all your components in one library package. Components in library packages can be used by multiple ASP applications and are run in the ASP application process. Use MTS Explorer to create a new package and then set the package's Activation property to Library.

You can also register transactional components in a Server package, a package that always runs in a separate process on the server. You use Server packages for your transactional components if you want to use role-based security or if you want your components to be accessible from applications on remote computers.

You must have Microsoft Transaction Server installed to use MTS Explorer.

Object Scope

Generally, you should not store objects created from an MTS component in the ASP Application or Session objects. MTS objects are deactivated when the transaction is completed. Because the Session and Application objects are intended for object instances that can be used across multiple ASP pages, you should not use them to hold objects that will be released at the end of a transaction.

An ASP script is the root, or start, of a declared transaction. Any MTS object used on a transactional ASP page is considered part of the transaction. When the transaction is completed, MTS objects used on the page are deactivated, including objects stored in the Session or Application object. Subsequent attempts to call the session-scope or application-scope object from another transactional page will fail.

Queuing Transactions

Updates to a database on a remote server could delay or abort the completion of a transaction due to network delays or failures. Because all portions of a transaction must be committed, your application might be held up waiting for the commit or abort message from the remote server or might abort a transaction because the database update could not be sent.

For updates that must be completed simultaneously, it is appropriate to abort or even delay the completion of the transaction until all participants in the transaction can commit. For example, an airline ticket-ordering application should complete both the debit to a customer's bank account and the credit to the airline's bank account simultaneously. If an update is integral to a transaction but could occur later than the other updates, you might prefer not to keep the customer waiting for the completion of the update. For example, a transaction to order an airline ticket might also send a special meal request to a food services vendor or update the customer's mileage. These activities must be completed, but could be completed later.

The Microsoft Message Queue Server enables you to bundle an update or set of updates into a transactional message that is delivered to a remote server. The Message Queue Server guarantees that updates will be delivered to the remote server, even if the network is currently unavailable. Your application receives a commit message and can continue with the transaction.