<html>
<head>
<title>ObjectContext Object</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div id="Description">
<table cellpadding="0" cellspacing="0" border="0" width="100%" class="main">
<tr>
<td valign="top" class="NAME">ObjectContext Object</td>
<td valign="top" class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td valign="top" colspan="2" class="description">


<p><!--<primary>ObjectContext
object</primary>--> <!--<primary>transactional
scripts</primary>--> <!--<primary>events</primary><secondary>ObjectContext
object</secondary>-->As of version 2.0, an important feature
of Active Server Pages 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.</p>




<p>ASP application transactions are controlled by
<!--<primary>Microsoft Transaction
Server</primary>--> <!--<primary>MTS (Microsoft
Transaction Server)</primary>-->
<!--<primary>Microsoft Transaction
Server</primary><seealso>ObjectContext object</seealso>-->
<!--<primary>MTS (Microsoft Transaction
Server)</primary><seealso>ObjectContext
object</seealso>-->Windows 2000 COM+ Component Services or
Windows NT's Microsoft Transaction Server (MTS). This piece of
the BackOffice suite allows control over all database actions coded
to use it. Support for transactional scripts is built into IIS and
Personal Web Server and does not require any special setup. Without
COM+ Component Services or, in ASP 2.0, 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 or COM+ Component Services
gives this support for very little extra coding—as long as the
database your application is connected to is Microsoft SQL Server or
it supports the XA protocol from the X/Open consortium. Note that
this means that file actions are not yet supported—or at least,
not automatically.</p>




<p>ASP's support of transactions is coded through the use of the
ObjectContext object, which represents the actual ObjectContext
object of COM+ Component Services 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.</p>




<p>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:</p>




<span class="PROGRAMLISTING"><pre>&lt;%@ TRANSACTION = Required %&gt;</pre></span>




<p>For more details on the
<span class="LITERAL">TRANSACTION</span><!--<primary>TRANSACTION
directive</primary>--> ASP directive, see <link linkend="ch11-1-fm2xml">Chapter 11</link>. Here it is important only that this line be
the first in your script; including this line alerts the web server
to use Component Services to ensure that the script succeeds or fails
as a whole.</p>




<p><!--<primary>committing transactions</primary>-->
<!--<primary>aborting transactions</primary>-->
<!--<primary>SetComplete method
(ObjectContext)</primary>--> <!--<primary>SetAbort
method (ObjectContext)</primary>-->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 Component Services (notably file actions), you can
specially code for these actions in the ObjectContext events
<!--<primary>OnTransactionCommit event
(ObjectContext)</primary>-->
<!--<primary>OnTransactionAbort event
(ObjectContext)</primary>-->OnTransactionCommit and
OnTransactionAbort. There are examples of all of these methods and
event procedures in the reference section later in this chapter.</p>




<!--
<p class="TITLE">ObjectContext Object Summary</p>




<dl>
<dt>Properties</dt>
<dd><p>None</p></dd>





<dt>Collections</dt>
<dd><p>None</p></dd>







<dt>Methods</dt>
<dd><p>SetAbort</p>




<p>SetComplete</p>
</dd>




<dt>Events</dt>
<dd><p>OnTransactionAbort</p>





<p>OnTransactionCommit</p>
</dd>

</dl>

-->
</td></tr>
</table>
</div>
<div id="CommentsTroubleshooting">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Comments/Troubleshooting</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2">&nbsp;</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">

<p><!--<primary>comments and
troubleshooting</primary><secondary>transactional
scripts</secondary>-->There are currently two very important
limitations in constructing transactional scripts:</p>

<ul><dd><p>Only database actions are supported, and only SQL Server and
databases that support the XA protocol are supported by COM+
Component Services or MTS.</p></dd><dd><p>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.</p></dd></ul>
<p>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 package. (MTS transactional support is provided only if the
component is registered. What's more, you should create your
own <!--<primary>library packages,
custom</primary>--> <!--<primary>custom library
packages</primary>-->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 <!--<primary>pooling library
packages</primary>-->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.)
</p>




<p>For more information on
the ObjectContext object and server components, see
<citetitle>Developing ASP Components</citetitle>, written by Shelley
Powers and published by O'Reilly &amp; Associates.</p>



<p class="footnote"> 



<p><!--<primary>transactions, object scope
and</primary>-->
<!--<primary>scope</primary><secondary>transactional
objects</secondary>--> <!--<primary>application-level
scope</primary><secondary>transactional objects
and</secondary>--> <!--<primary>global
variables</primary><secondary>transactional objects
and</secondary>--> <!--<primary>ObjectContext
object</primary><secondary>object scope
and</secondary>-->Note that you should not give objects
functioning in transactions <!--<primary>session-level
scope</primary><secondary>transactional objects
and</secondary>-->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.</p>




<p>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.</p>




<p>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 COM+ Component Services or
MTS, and therefore are not documented here.</p>




<p>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.</p>
</td>
</tr>
</table>
</div>
<div id="SetAbort">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
SetAbort</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">ObjectContext.SetAbort</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>SetAbort method
(ObjectContext)</primary>--> <!--<primary>aborting
transactions</primary>--> <!--<primary>ObjectContext
object</primary><secondary>method and event
reference</secondary>-->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.</p>




<p>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 or COM+ Component Services 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.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;%

' 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

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>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 a
transaction (notably file actions).</p>




<p>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.</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="SetComplete">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
SetComplete</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">ObjectContext.SetComplete</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>SetComplete method
(ObjectContext)</primary>--> <!--<primary>committing
transactions</primary>-->Signals the successful completion
of a transaction. When it is called, the code in the
OnTransactionCommit event procedure code is processed if it exists.</p>




<p>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.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>See the example in the previous section, "SetAbort."</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>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.</p>




<p>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.</p>



</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="OnTransactionAbort">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
OnTransactionAbort</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">OnTransactionAbort( )</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p>The <!--<primary>OnTransactionAbort event
(ObjectContext)</primary>-->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.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;% 

' The following code procedure is processed when the code in 
' the SetAbort method example is processed.
Sub OnTransactionAbort ( )
%&gt;
   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.
&lt;%
   ' Clean up any nontransactional actions here...

End Sub

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>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.</p>




<p>You also should use the OnTransactionAbort event to inform the client
that the transaction has failed.</p>




<p>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.</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="OnTransactionCommit">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
OnTransactionCommit</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">OnTransactionCommit( )</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p>The <!--<primary>OnTransactionCommit event
(ObjectContext)</primary>-->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.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;% 

' The following code procedure is processed when the code in 
' the SetComplete method example is processed.
Sub OnTransactionCommit ( )
%&gt;
   Your book sales transaction was completed.
   Thank you for your sale.

&lt;%
   Session("intTotalSales") = Session("intTotalSales") + 1

   ' Process any nontransactional code here...

End Sub

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>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.</p>




<p>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.


</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
</body>
</html>