    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Transactions with Delegates in C#</title>
        <link>https://members.accu.org/index.php/journals/830</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 17, #4 - Aug 2005 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c95/">174</a>
                    (12)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c95-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c95+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Transactions with Delegates in C#</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 August 2005 05:00:00 +01:00 or Wed, 03 August 2005 05:00:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;<p>The Delegate type is a powerful feature of C#. This article introduces delegates, and shows how they can be used to solve a common problem: ensuring that a series of database updates occur as a single operation by use of a transaction. </p></p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e31" id=
"d0e31"></a>Introduction</h2>
</div>
<p>The Delegate type is a powerful feature of C#. This article
introduces delegates, and shows how they can be used to solve a
common problem: ensuring that a series of database updates occur as
a single operation by use of a transaction. The solution presented
is flexible and minimises duplication of code.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e36" id=
"d0e36"></a>Transactions</h2>
</div>
<p>Transactions are essential for maintaining data integrity within
computer systems; they seek to guarantee that logically dependent
data are amended together in (effectively) a single operation. If
an error occurs during that operation, the entire operation fails,
and no changes are persisted. Indeed, the ACID () properties of a
database rely heavily on correctly implemented
transactions<sup>[<a name="d0e41" href="#ftn.d0e41" id=
"d0e41">1</a>]</sup>.</p>
<p>However, the application developer should not be forced to
memorise the details of transaction-handling code in order to
perform 'ACID-ic' data updates: transaction code should be
transparent, and not interfere with core application logic.</p>
<p>The 'boiler-plate' transaction code (i.e. that which is generic)
would best be hidden behind a programming interface that feels
'natural'; ideally, we would have just a single point in the code
for handling transactions. With the complex details of transactions
hidden, programmers are free to concentrate on application
logic.</p>
<p>We need a solution which:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>Minimises proliferation of transaction code.</p>
</li>
<li>
<p>Hides the details of transaction code</p>
</li>
<li>
<p>Allows data update code to be defined separately from
transaction code.</p>
</li>
</ol>
</div>
<div class="sidebar">
<p class="title c4">Transactions and DataSets in C#</p>
<p>Transactions in C# [<a href="#Specification">Specification</a>,
<a href="#Bergin">Bergin</a>] are simplified by use of the
Framework Class Library (FCL) System.Data.IDbTransaction interface,
which provides Commit() and Rollback() methods, and a Connection
property, allowing the transaction to take place in the context of
a particular database connection. This interface allows us to use
the same database update logic with different database types and
transaction models.</p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e72" id="d0e72"></a>Potential
Solutions</h2>
</div>
<p>The programmatic nature of transactions can be summarised
as:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>BEGIN transaction</p>
</li>
<li>
<p>EXECUTE updates in context of transaction</p>
</li>
<li>
<p>COMMIT/ROLLBACK transaction depending on result of EXECUTE.</p>
</li>
</ol>
</div>
<p>The BEGIN and COMMIT/ROLLBACK actions represent the
'boiler-plate' code, whereas EXECUTE is dependent on specific data
update requirements. Figure 1 shows this relationship.</p>
<div class="figure"><a name="d0e89" id="d0e89"></a>
<div class="mediaobject c5"><img src="/var/uploads/journals/resources/transaction.png"
align="middle" alt=
"Generalised transaction logic. The EXECUTE stage is logically separate from the BEGIN and COMMIT/ROLLBACK stages."></div>
<p class="title c4">Figure 1. Generalised transaction logic. The
EXECUTE stage is logically separate from the BEGIN and
COMMIT/ROLLBACK stages.</p>
</div>
<p>Here are some possible schemes for using transactions:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>Wrap BEGIN and COMMIT/ROLLBACK around every EXECUTE operation
(Figure 2). This provides flexibility in the definition of EXECUTE,
but at the expense of gratuitous code duplication, with associated
maintainability problems: if changes are needed to the code for
BEGIN or COMMIT/ROLLBACK, those changes must be propagated
throughout the application code.</p>
<div class="figure"><a name="d0e101" id="d0e101"></a>
<div class="mediaobject c5"><img src="/var/uploads/journals/resources/Duplication.png"
align="middle" alt=
"Transaction code explicitly surrounding each data update."></div>
<p class="title c4">Figure 2. Transaction code explicitly
surrounding each data update.</p>
</div>
</li>
<li>
<p>Derive a group of data update classes from a common base class.
Place the BEGIN and COMMIT/ROLLBACK code within a method on the
base class, and have it call an overridden virtual method on
derived classes to perform the EXECUTE logic. The limitation of
this scheme is that a type hierarchy is imposed on data update
code, which may not fit with existing class models, and which will
likely lead to 'brittle' code and inflexibility for programmers.
This is shown in Figure 3 - the EXECUTE methods are restricted in
functionality by being derived from the same base class.</p>
<div class="figure"><a name="d0e110" id="d0e110"></a>
<div class="mediaobject c5"><img src=
"/var/uploads/journals/resources/execute_methods.png" align="middle" alt=
"A base class handles the BEGIN and COMMIT/ROLLBACK logic, with overridden EXECUTE methods containing data update logic. Data update methods are limited to a single class hierarchy"></div>
<p class="title c4">Figure 3. A base class handles the BEGIN and
COMMIT/ROLLBACK logic, with overridden EXECUTE methods containing
data update logic. Data update methods are limited to a single
class hierarchy</p>
</div>
</li>
<li>
<p>Use the Automatic Transactions feature supported by .NET
[<a href="#Anonymous">Anonymous</a>]. This makes use of COM+/MTS
technologies, and requires some specific code and application
modifications that may not be applicable or suitable in many cases,
and does not provide precise control over the transaction used for
a given method.</p>
</li>
</ol>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e122" id="d0e122"></a>A Solution:
C# Delegates</h2>
</div>
<p>The ECMA specification [<a href=
"#Specification">Specification</a>] for C# introduces the delegate
type thus:</p>
<div class="blockquote">
<blockquote class="blockquote">
<p>Delegates enable scenarios that some other languages have
addressed with function pointers. However, unlike function
pointers, delegates are object-oriented and
type-safe.<sup>[<a name="d0e133" href="#ftn.d0e133" id=
"d0e133">2</a>]</sup></p>
</blockquote>
</div>
<p>A delegate is declared as follows:</p>
<pre class="programlisting">
public delegate void SomeDelegate(int i);

The delegate SomeDelegate expects a single int parameter and returns no value. Note the keyword delegate. The delegate is invoked as follows:
</pre>
<pre class="programlisting">
public class SomeClass
{
  // ...
  // Signature matches that of delegate
  public void SomeMethod(int i) { 
     /* do     something here */ }
  // ...
}
public class AnotherClass
{
  public void CallDelegate(int i)
  {
    SomeClass c = new SomeClass();
    // Wrap the method as a delegate
    SomeDelegate d = new
        SomeDelegate(c.SomeMethod);

       #// Invoke the delegate
    d(i);
  }
}
</pre>
<p>The delegate acts a typed 'wrapper' around another method.
Following instantiation, the delegate object is 'free' of the class
in which its wrapped method is defined; the delegate can be treated
as (and in fact is) a first-class object in its own right. For
example, the delegate can be stored in a container or list of some
sort for later processing, if required. So, delegates can be
considered as akin to type-safe function pointers (or somewhat
analogous to function objects in C++ and Python).</p>
<p>By placing all data update code inside delegate methods, it is
possible to trigger all data updates in the same generic way:
namely, by invoking the appropriate delegates. The parameters
expected by one update method are identical to (or compatible with)
those expected by all other update methods. We can thus guarantee
that every delegate-based update method has access to the required
IDbTransaction reference to use during data updates. Referring back
to Figure 1 and the three stages of a transactional data update, we
now have a way to link any EXECUTE step (contained within a
delegate) to the transaction associated with our BEGIN and
COMMIT/ROLLBACK logic. See Figure 4.</p>
<div class="figure"><a name="d0e148" id="d0e148"></a>
<div class="mediaobject c5"><img src=
"/var/uploads/journals/resources/transaction_delegates.png" align="middle" alt=
"Transactions using Delegates. The delegate EXECUTE methods can be invoked in a generic way (outer box) but may belong to disparate classes and contain very different logic."></div>
<p class="title c4">Figure 4. Transactions using Delegates. The
delegate EXECUTE methods can be invoked in a generic way (outer
box) but may belong to disparate classes and contain very different
logic.</p>
</div>
<p>However, C# delegates sport another feature which is
particularly useful in the context of this articleiii: they have
'multi-cast' abilities. Delegates of the same type can be
'combined' or concatenated (using the overloaded operator +=),
producing a new delegate object which will - when invoked - call
each of the original delegates in turn. This multi-cast feature can
be used to chain together a sequence of data update calls, without
the need explicitly to manage the group of delegates in the chain.
For example, data updates might be queued on a background thread,
and then submitted together as a batch. The code invoking the
multi-cast delegate need not know how many individual delegates
will be invoked; the invoked delegate handles this
automatically.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e156" id="d0e156"></a>Delegates:
Recapitulation</h2>
</div>
<p>Delegates will allow us to place our database update code in any
class we choose, providing we arrange for the method signature of
the update methods to match that of a particular delegate. We can
pass into the delegate method the IDbTransaction reference for use
during data update.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e161" id="d0e161"></a>A Working
Example</h2>
</div>
<p>The following code demonstrates the ideas presented so far in
working code.</p>
<p>First we declare our delegate which expects two parameters:
<i class="parameter"><tt>sender</tt></i> and <i class=
"parameter"><tt>args</tt></i> (details follow later).</p>
<pre class="programlisting">
public delegate void TransactionedOperationDelegate
    (TransactionWrapper sender, 
     TransactionArgs args);
</pre>
<p>Next we declare a lightweight class to represent a database
update operation:</p>
<pre class="programlisting">
public abstract class TransactionedOperation
{
  public TransactionedOperationDelegate Execute; 
}
</pre>
<p>We must derive sub-classes from this class, as it is marked
<tt class="literal">abstract</tt>, and therefore not instantiable.
It holds a delegate reference in its <tt class=
"varname">Execute</tt> field. We will return to this shortly.</p>
<p>Referring to the basic transaction model (see Potential
Solutions, above; Figure 1), we can map out the method required to
implement the BEGIN and COMMIT/ROLLBACK logic.<sup>[<a name=
"d0e190" href="#ftn.d0e190" id="d0e190">3</a>]</sup></p>
<p>The various data update operations passed to this method should
be treated as a single, atomic operation:</p>
<pre class="programlisting">
// Make all operations into one atomic operation
public void MakeAtomic
    (TransactionedOperation[] operations)
{
  // Connection is set elsewhere
  this.Connection.Open();
  try
  {
    // BEGIN
    using (IDbTransaction transaction =
        this.Connection.BeginTransaction())
    {
      try
      {
      /// Prepare, then call each operation
       /// Any exceptions will abort the transaction
 
        foreach (TransactionedOperation 
            operation in operations)
          {
            // EXECUTE
            // Invoke the delegate here!
            // i.e. operation.Execute(...)
            // ...
          }
          // COMMIT...
          transaction.Commit();
      }
      catch (Exception exception)
      {
        // ... or ROLLBACK
        transaction.Rollback();

        // TODO: Log the exception here

        // Re-throw exception
        throw;
      }
    }
  }
  finally
  {
    this.Connection.Close();
  }
}
</pre>
<p>The code as shown implements the BEGIN and COMMIT/ROLLBACK
stages of the transaction logic. What is missing is the EXECUTE
stage; that is, the invocation of the data update delegate
contained in each <tt class="classname">TransactionedOperation</tt>
in the <tt class="varname">operations</tt> array. What sort of
parameters should we pass to the delegate? We clearly cannot make
any sensible generalised assertions about the kind of parameters
that might be needed by any given data update method. After all,
one of the goals of using delegates is to allow data update code to
reside in any arbitrary class; locking down the parameters would
negate that flexibility.</p>
<p>The solution is to allow calling code to 'hook on' parameters to
the <tt class="classname">TransactionedOperation</tt> parameter, by
deriving a sub-class (as mentioned above), and defining new
fields<sup>[<a name="d0e210" href="#ftn.d0e210" id=
"d0e210">4</a>]</sup> to store the required parameters. For
example:</p>
<pre class="programlisting">
public class CustomTransactionedOperation : TransactionedOperation
{
  // hook arbitrary data...
  public CustomTransactionedOperation
     (CustomDataSet dataSet)
  {
    this.Example = dataSet.ExampleData;
  }
  public readonly string Example;
}
</pre>
<p>A sub-class <tt class=
"classname">CustomTransactionedOperation</tt> is derived from the
base class <tt class="classname">TransactionedOperation</tt>. A
delegate method can now access the <tt class="varname">Example</tt>
field of the operation parameter.</p>
<p>Remember that the delegate method takes two parameters: a
reference to the <tt class="classname">TransactionWrapper</tt>
calling the delegate (the ubiquitous 'sender'), and a parameter of
type <tt class="classname">TransactionArgs</tt>. We use this second
parameter to pass essential information to the delegate method:</p>
<pre class="programlisting">
public class TransactionArgs : EventArgs 
    // for convenience
{
  public TransactionArgs(
      IDbConnection connection,
      IDbTransaction transaction,
      TransactionedOperation operation)
  {
    this.Connection = connection;
    this.Transaction = transaction;
    this.Operation = operation;
  }
  public readonly IDbConnection Connection;
  public readonly IDbTransaction Transaction;
  public readonly TransactionedOperation
      Operation;
} 
</pre>
<p>The <tt class="classname">CustomTransactionedOperation</tt>
(with its custom data fields) can be attached to the <tt class=
"classname">TransactionArgs</tt> parameter, thereby allowing
arbitrary information to be passed to the delegate method.</p>
<p>Our code for invoking an operation delegate therefore looks like
this:</p>
<pre class="programlisting">
// Connection is an IDbConnection reference
// transaction is an IDbTransaction reference
// operation is a TransactionedOperation
// reference
TransactionArgs args = new TransactionArgs(
    Connection, transaction, operation);
operation.Execute(this, args);
</pre>
<p>It might seem slightly strange that we use the operation
parameter twice (once to allow us to call the delegate, and a
second time to pass custom parameters to the delegate inside args):
this is largely for convenience, although also allows for
flexibility in the management of update operations.</p>
<p>All that is left now is to prepare the <tt class=
"classname">TransactionedOperation</tt> and use the <tt class=
"classname">TransactionWrapper</tt> class to make the data update
operation(s) atomic:</p>
<pre class="programlisting">
// Some arbitrary update code, somewhere...
public void UpdateCustomDetails(CustomDataSet dataSet)
{
  // Connect here to a SQL Server database -
  // could change
  IDbConnection connection = new
      System.Data.SqlClient.SqlConnection
      ( /* connection string */ );
  TransactionWrapper transactionWrapper = new
      TransactionWrapper(connection);

  // Hook the data onto the operation 
  // parameters
  CustomDataUpdate customDataUpdate = new
      CustomDataUpdate();
  CustomTransactionedOperation operation = new
      CustomTransactionedOperation(dataSet);
  operation.Execute += new
      TransactionedOperationDelegate(
      customDataUpdate.UpdateData);
/* chain another delegate here if required:
operation.Execute += new
    TransactionedOperationDelegate(
    SomeOtherDelegateMethod);
*/
  // wrap in transaction
  transactionWrapper.MakeAtomic(operation);
}
</pre>
<p>The delegate used here is the <tt class=
"methodname">UpdateData()</tt> method of a <tt class=
"classname">CustomDataUpdate</tt> instance. This is the method that
will make use of the <tt class="classname">IDbTransaction</tt>
transaction to perform atomic updates. Other update methods that
expect the same dataset<sup>[<a name="d0e272" href="#ftn.d0e272"
id="d0e272">5</a>]</sup> can be chained on to the first delegate
(shown in comments). Each delegate in the multi-cast chain will
receive the same arguments. The <tt class=
"methodname">UpdateData()</tt> method could look like this:</p>
<pre class="programlisting">
public class CustomDataUpdate
{
// The delegate method
public void UpdateData(TransactionWrapper sender, TransactionArgs args)
{
// Expect special operation type
CustomTransactionedOperation operation = args.Operation as CustomTransactionedOperation;

SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Transaction = args.Transaction as System.Data.SqlClient.SqlTransaction;
sqlCommand.Connection = args.Connection as System.Data.SqlClient.SqlConnection;

// Use custom params from operation object
sqlCommand.CommandText = operation.Example; // etc.

sqlCommand.ExecuteNonQuery();
}
}
</pre>
<p>Clearly, a production system would employ somewhat more
sophisticated logic, but the principle remains!</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e286" id="d0e286"></a>Roundup</h2>
</div>
<p>The code presented above achieves the three goals set out at the
beginning of this article: there is no proliferation of transaction
code (only a single method, <tt class=
"methodname">TransactionWrapper.MakeAtomic()</tt> holds such
code<sup>[<a name="d0e294" href="#ftn.d0e294" id=
"d0e294">6</a>]</sup>); data update methods need only use the
IDbTransaction reference when calling into the database (no other
details are needed); and data update methods can be defined in
arbitrary locations, and can require arbitrary data, and all
participate in transactions in the same way. See Figure 4.</p>
<p>The scheme provides additional benefits, such as the ability to
log all details of a transaction at a single point (in the
TransactionWrapper).</p>
<p>Finally, the scheme implements a modified version of the Command
Pattern [<a href="#GoF">GoF</a>] with the operation.Execute()
method [<a href="#Command">Command</a>] functionality, and the
TransactionWrapper is arguably an implementation of the
Fa&ccedil;ade Pattern [<a href="#Facade">Facade</a>].</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e314" id="d0e314"></a>Observations
and Notes</h2>
</div>
<p>In this scheme all database updates take place synchronously
within the same <tt class="classname">IDbConnection</tt> context.
Use of a single connection is normally essential for transactions
(although MS SQL Server allows sharing of transaction space between
connections via a special Stored Procedure <tt class=
"function">sp_bindsession</tt> - see [<a href=
"#Sharing">Sharing</a>]). Delegates are processed (and data
updated) in order of submission to the <tt class=
"methodname">TransactionWrapper.MakeAtomic()</tt> method.</p>
<p>C# delegates also support asynchronous execution, but this
scenario has not been tested with the scheme presented here. If the
ordering of data updates is not important, then it is possible that
asynchronous delegate execution could be made to work with this
code, but mixing asynchronous calls with transactions could lead to
problems: transactions typically lock (part of) a database during
execution, and long-running transactional asynchronous method calls
could therefore cause performance bottlenecks.</p>
<p>Any method that performs data update using the technique
presented here must use the provided <tt class=
"classname">IDbTransaction</tt> interface. A deadlock condition is
likely to ensue if an application mixes transactional database
requests with non-transactional requests. Enforcing this
requirement is probably largely down to good practice.</p>
<p>The scheme is not designed to support Distributed Transactions,
although could in principle be modified for such a purpose, if a
suitable implementation of the IDbTransaction interface were
available.</p>
<p>It might be useful to consider providing event notifications at
certain stages of the transaction, such as <tt class=
"classname">TransactionStarted</tt>, <tt class=
"classname">TransactionCommitted</tt>, <tt class=
"classname">TransactionAborted</tt>, etc. This would allow
listeners to register for notification of these events, probably in
the context of the submission to the <tt class=
"classname">TransactionWrapper</tt> of a group of transactional
operations.</p>
<p>The code demonstrated here has been tested only with the
Microsoft version of C#, running under the .NET Platform (versions
1.0 and 1.1) [<a href="#dotNET">dotNET</a>], but should work with
little or no modification under alternative C# implementations,
such as Mono [<a href="#Mono">Mono</a>].</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e362" id="d0e362"></a>Summary</h2>
</div>
<p>This article introduced the C# Delegate type, and showed how it
can be used to coordinate and simplify the management of
transactional database updates. We have seen a coding scheme using
Delegates which keeps tight control of the transaction logic, while
also allowing a good deal of flexibility in the definition and
location of database update code.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e367" id="d0e367"></a>Full Source
Code</h2>
</div>
<pre class="programlisting">
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
namespace Library
{
  #region Delegates
  /// &lt;summary&gt;
  /// A delegate for data updates which
  /// require a transaction i.e. need to be atomic
  /// &lt;/summary&gt;
  public delegate void
      TransactionedOperationDelegate(
      TransactionWrapper sender,
      TransactionArgs args);
  #endregion
  #region Operation Parameters Class
  /// &lt;summary&gt;
  /// Base class for all classes implementing
  functionality of parameters for transactioned
  operations
  /// Derive sub-classes from this, and customise
  with fields etc.
  /// In the transactioned operation, check the type
  of the object.
  /// &lt;/summary&gt;
  public abstract class TransactionedOperation
  {
    public TransactionedOperationDelegate Execute;
    // cannot use 'event' designation as we are
    calling this multicast from outside the defining
    class
  }
  #endregion
#region Transaction Args
/// &lt;summary&gt;
/// Lightweight class representing arguments for a transactionable operation
/// &lt;/summary&gt;
public class TransactionArgs : EventArgs
{
  public TransactionArgs(
      IDbConnection connection,
      IDbTransaction transaction,
      TransactionedOperation operation)
    {
      this.Connection = connection;
      this.Transaction = transaction;
      this.Operation = operation;
    }
    public readonly IDbConnection Connection;
    public readonly IDbTransaction Transaction;
    public readonly TransactionedOperation
          Operation;
  }
  #endregion
  #region TransactionWrapper Class
  /// &lt;summary&gt;
  /// Provides a fairly generic way to wrap any
  operation within a transaction.
  /// The functionality is implemented using
  delegates.
  /// &lt;/summary&gt;
  public class TransactionWrapper
  {
    #region .ctor public TransactionWrapper(
          IDbConnection connection)
      {
        if (null == connection)
        {
          throw new ArgumentNullException(
                &quot;connection&quot;);
        }
      this.Connection = connection;
    }
    #endregion

    #region Fields
    internal readonly IDbConnection Connection;
    #endregion

    /// &lt;summary&gt;
    /// Makes an operation atomic by allowing
    all data updates it contains easily to share the
    same transaction
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;operations&quot;&gt;An operation
    which should use a single transaction&lt;/param&gt;
    public void MakeAtomic(
                TransactionedOperation operation)
    {
      #region Parameter checks
      if (null == operation)
      {
        throw new ArgumentNullException(
              &quot;operation&quot;);
      }
      #endregion

      MakeAtomic(new TransactionedOperation[]
            {operation});
    }

    /// &lt;summary&gt;
    /// Makes one or more potentially disparate 
    operations atomic by allowing them easily to 
    share the same transaction
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;operations&quot;&gt;An array of 
    operations which should share the same 
    transaction&lt;/param&gt;
    public void MakeAtomic(
          TransactionedOperation[] operations)
    {
      #region Parameter checks
      if (null == operations)
      {
        throw new ArgumentNullException(
              &quot;operations&quot;);
      }

      for (int i=0; i &lt; operations.Length;++i)
      {
        TransactionedOperation operation 
              = operations[i];

        if (null == operation)
        {
          throw new ArgumentNullException(
                &quot;operation&quot;
        }
        if (null == operation.Execute)
        {
          throw new ArgumentNullException(
             String.Format(
             &quot;operation.Execute at index {0}&quot;,i));
        }
      }
      #endregion

      #region Main functionality
      this.Connection.Open();
      try
      {
        using (IDbTransaction transaction = 
           this.Connection.BeginTransaction())
        {
        try
          {
           /// Prepare, then call the operation
           /// Any exceptions will cause the 
           transaction to be aborted
           /// All relevent objects have been
           checked for nullness prior to this
           /// 
          foreach (TransactionedOperation
                operation in operations)
            { 
              TransactionArgs args = new
                   TransactionArgs(Connection,
                   transaction, operation);
              operation.Execute(this, args);
  // TODO: Log the operation here if required.
            }
            transaction.Commit();
          }
          catch (Exception exception)
          {
            transaction.Rollback();
  // TODO: Log the error here
            throw;
          }
        }
      }
      finally
      {
// Strictly speaking, there is no need for this close here because IDbConnection 
// implements IDisposable - the connection will be closed when the object is Garbage-Collected
        this.Connection.Close();
      }
        #endregion
      }
    }
    #endregion
  }
  namespace Application
  {
    /// &lt;summary&gt;
    /// Example logging interface
    /// &lt;/summary&gt;
    public interface ILog
    {
      void Write(DateTime dateTime, 
                IDbConnection connection,
                Library.TransactionArgs args);
    }
    /// &lt;summary&gt;
    /// Some kind of custom data set
    /// &lt;/summary&gt;
    public class CustomDataSet : DataSet
    {
      public string ExampleData;
    }
    /// &lt;summary&gt;
    /// 
    /// &lt;/summary&gt;
    public class CustomTransactionedOperation
          : Library.TransactionedOperation
    {
      public CustomTransactionedOperation
            (CustomDataSet dataSet)
      {
        this.Example = dataSet.ExampleData;
      }
      public readonly string Example;
    }
    /// &lt;summary&gt;
    /// A base class for data update 
    operations. Provides logging capabilities.
    /// &lt;/summary&gt;
    public abstract class BaseDataUpdate
    {
      public BaseDataUpdate (ILog log)
        {
          this.log = log;
        }

      private ILog log;

      private bool loggingEnabled;
      public bool LoggingEnabled
      {
        get { return loggingEnabled; }
        set { loggingEnabled = value; }
      }

      public virtual void UpdateData(
            Library.TransactionWrapper sender,
            Library.TransactionArgs args)
      {
        log.Write(DateTime.Now,
                  sender.Connection, args);
      }
    }

    /// &lt;summary&gt;
    /// An example class which performs data
    updates.
    /// &lt;/summary&gt;

    public class 
          CustomDataUpdate : BaseDataUpdate
    {
      public CustomDataUpdate 
            (ILog log) : base (log) { }

      public override void UpdateData
           (Library.TransactionWrapper sender,
            Library.TransactionArgs args)
      {
        CustomTransactionedOperation
              operation = args.Operation as
              CustomTransactionedOperation;
        SqlCommand sqlCommand = 
              new SqlCommand();
        sqlCommand.Transaction =
              args.Transaction as
              System.Data.SqlClient
              .SqlTransaction;
        sqlCommand.Connection 
              = args.Connection as
              System.Data.SqlClient
              .SqlConnection;

        sqlCommand.CommandText 
              = operation.Example;
              /* Some suitable text here */

        sqlCommand.ExecuteNonQuery(); // TODO:
               note the number of rows affected and
               publish via an event 

        base.UpdateData(sender, args);
      }
    }

    /// &lt;summary&gt;
    /// Example class demonstrating a stand
    alone method used in data updates.
    /// &lt;/summary&gt;
    public class StandaloneDataUpdate
    {
      /// &lt;summary&gt;
      /// This method does not need custom
      TransactionArgs parameter. 
      /// &lt;/summary&gt;
      /// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;
      /// &lt;param name=&quot;args&quot;&gt;&lt;/param&gt;
        public void SomeMethod(
              Library.TransactionWrapper sender,
              Library.TransactionArgs args)
        {
          SqlCommand sqlCommand = new SqlCommand();
          sqlCommand.Transaction = args.Transaction
            as System.Data.SqlClient.SqlTransaction;
          sqlCommand.Connection = args.Connection as
            System.Data.SqlClient.SqlConnection;

          sqlCommand.CommandText = &quot;&quot;; 
          /* Some suitable text here */

          sqlCommand.ExecuteNonQuery(); 
        }
      }

      /// &lt;summary&gt;
      /// Some other kid of data set
      /// &lt;/summary&gt;
      public class SpecialDataSet : DataSet
      {
        public int MoreExampleData;
      }

      /// &lt;summary&gt;
      /// Example class where the data update method
      is actually part of the class. 
      /// This avoid the need to redefine separate 
      classes for the update method and the 
      parameters but might reduce flexibility.
      /// &lt;/summary&gt;
      public class AggregateTransactionedOperation :
            Library.TransactionedOperation
      {
        public AggregateTransactionedOperation 
              (SpecialDataSet dataSet)
        {
          this.Example = dataSet.MoreExampleData;
        }

        public readonly int Example;

        public static void SelfContainedUpdateData
              (Library.TransactionWrapper sender,
               Library.TransactionArgs args)
        { 
            // TODO: Paramter checks

          AggregateTransactionedOperation operation 
                = args.Operation as 
                AggregateTransactionedOperation;

          SqlCommand sqlCommand = new SqlCommand();
          sqlCommand.Transaction = args.Transaction
                 as System.Data.SqlClient.SqlTransaction;
          sqlCommand.Connection = args.Connection as
                 System.Data.SqlClient.SqlConnection;

          sqlCommand.CommandText = &quot;&quot;;
          /* Some suitable text here */

          sqlCommand.ExecuteNonQuery();
        }
      }

      /// &lt;summary&gt;
      /// Manager class which co-ordinates access to
     data update operations
    /// &lt;/summary&gt;
    public class DataUpdateManager
    {
      private ILog log = null; // Initialise this
            somewhere...

    /// &lt;summary&gt;
    /// 
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;dataSet&quot;&gt;&lt;/param&gt;
    public void UpdateCustomDetails
          (CustomDataSet dataSet)
    {
      IDbConnection connection 
            = new System.Data.SqlClient.SqlConnection
            ( /* Connection string goes here*/ );
      Library.TransactionWrapper transactionWrapper =
            new Library.TransactionWrapper(connection);
      // Hook the data onto the operation parameters
      CustomDataUpdate customDataUpdate = 
            new CustomDataUpdate(this.log);
      CustomTransactionedOperation operation =
            new CustomTransactionedOperation(dataSet);
      operation.Execute += 
            new Library.TransactionedOperationDelegate
            (customDataUpdate.UpdateData);

      transactionWrapper.MakeAtomic(operation);
    }

    /// &lt;summary&gt;
    /// Performs multiple updates in a single 
    transaction, with disparate (but presumably 
    related) data.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;dataSet1&quot;&gt;first data set&lt;/param&gt;
    /// &lt;param name=&quot;dataSet2&quot;&gt;second data set&lt;/param&gt;
    public void UpdateMultipleDetails
          (CustomDataSet dataSet1,
           SpecialDataSet dataSet2)
    {
      // Prepare the connection
      IDbConnection connection = 
            new System.Data.SqlClient.SqlConnection
            ( /* Connection string goes here*/ );
      Library.TransactionWrapper transactionWrapper =
            new Library.TransactionWrapper(connection);
      // Hook data for first operation
      CustomDataUpdate customDataUpdate = 
            new CustomDataUpdate(this.log); 
      CustomTransactionedOperation operation1 = 
            new CustomTransactionedOperation(dataSet1);
      operation1.Execute +=
            new Library.TransactionedOperationDelegate
            (customDataUpdate.UpdateData);

      // Hook data for second operation
      AggregateTransactionedOperation operation2 = 
            new AggregateTransactionedOperation
            (dataSet2);
      operation2.Execute += 
            new Library.TransactionedOperationDelegate
            (AggregateTransactionedOperation
            .SelfContainedUpdateData);
      // Collect together the operations and make them
      atomic
      Library.TransactionedOperation[] operations = 
            new Library.TransactionedOperation[] 
            {operation1, operation2};
      transactionWrapper.MakeAtomic(operations);
    }
  }
}
</pre></div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e372" id="d0e372"></a>References</h2>
</div>
<div class="bibliomixed"><a name="GoF" id="GoF"></a>
<p class="bibliomixed">[GoF] <span class="citetitle"><i class=
"citetitle">Design Patterns: Elements of Reusable Object-Oriented
Software</i></span> - E. Gamma, R. Helm, R. Johnson, J. Vlissides:
, Addison-Wesley, Reading, 1995. ISBN 0-201-63361-2</p>
</div>
<div class="bibliomixed"><a name="Facade" id="Facade"></a>
<p class="bibliomixed">[Facade] Facade Pattern: <span class=
"bibliomisc"><a href="http://en.wikipedia.org/wiki/Facade_pattern"
target="_top">http://en.wikipedia.org/wiki/Facade_pattern</a> and
<a href="http://www.dofactory.com/Patterns/PatternFacade.aspx"
target=
"_top">http://www.dofactory.com/Patterns/PatternFacade.aspx</a></span></p>
</div>
<div class="bibliomixed"><a name="Command" id="Command"></a>
<p class="bibliomixed">[Command] Command Pattern: <span class=
"bibliomisc"><a href="http://en.wikipedia.org/wiki/Command_pattern"
target="_top">http://en.wikipedia.org/wiki/Command_pattern</a> and
<a href="http://www.dofactory.com/Patterns/PatternCommand.aspx"
target=
"_top">http://www.dofactory.com/Patterns/PatternCommand.aspx</a></span></p>
</div>
<div class="bibliomixed"><a name="Specification" id=
"Specification"></a>
<p class="bibliomixed">[Specification] C# Language Specification:
<span class="bibliomisc"><a href=
"http://www.ecma-international.org/publications/standards/Ecma-334.htm"
target=
"_top">http://www.ecma-international.org/publications/standards/Ecma-334.htm</a></span></p>
</div>
<div class="bibliomixed"><a name="ACID" id="ACID"></a>
<p class="bibliomixed">[ACID] ACID definition: <span class=
"bibliomisc"><a href="http://en.wikipedia.org/wiki/ACID" target=
"_top">http://en.wikipedia.org/wiki/ACID</a></span></p>
</div>
<div class="bibliomixed"><a name="AOP" id="AOP"></a>
<p class="bibliomixed">[AOP] Aspect-Oriented Programming (AOP) -
introduction: <span class="bibliomisc"><a href=
"http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html" target=
"_top">http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html</a></span></p>
</div>
<div class="bibliomixed"><a name="Bergin" id="Bergin"></a>
<p class="bibliomixed">[Bergin] Introduction To C#, Mike Bergin,
<span class="citetitle"><i class="citetitle">CVu</i></span> 16.3,
June 2004</p>
</div>
<div class="bibliomixed"><a name="Mono" id="Mono"></a>
<p class="bibliomixed">[Mono] Mono: <span class=
"bibliomisc"><a href="http://www.mono-project.com/" target=
"_top">http://www.mono-project.com/</a></span></p>
</div>
<div class="bibliomixed"><a name="dotNET" id="dotNET"></a>
<p class="bibliomixed">[dotNET] .NET Framework: <span class=
"bibliomisc"><a href="http://msdn.microsoft.com/netframework/"
target=
"_top">http://msdn.microsoft.com/netframework/</a></span></p>
</div>
<div class="bibliomixed"><a name="Sharing" id="Sharing"></a>
<p class="bibliomixed">[Sharing] <span class="bibliomisc">Sharing
transactions between connections on SQL Server using
sp_bindsession: <a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_sp_ba-bz_9ini.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_sp_ba-bz_9ini.asp</a>
and Creating strongly-typed DataSet classes using the xsd.exe tool:
<a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcongeneratingstronglytypeddataset.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcongeneratingstronglytypeddataset.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="Auto" id="Auto"></a>
<p class="bibliomixed">[Auto] Automatic transactions in .NET:
<span class="bibliomisc"><a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconautomatictransactionsnetframeworkclasses.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconautomatictransactionsnetframeworkclasses.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="Anonymous" id="Anonymous"></a>
<p class="bibliomixed">[Anonymous] Anonymous methods in C# 2.0:
<span class="bibliomisc"><a href=
"http://msdn.microsoft.com/vcsharp/2005/overview/language/anonymousmethods/"
target=
"_top">http://msdn.microsoft.com/vcsharp/2005/overview/language/anonymousmethods/</a></span></p>
</div>
</div>
<div class="footnotes"><br>
<hr class="c6" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e41" href="#d0e41" id=
"ftn.d0e41">1</a>]</sup> Here, 'transaction' generally refres to a
one-phase operation between a single database and a single
application. Distributed Transactions (between multiple data
sources and/or applications) are out of the scope of this
discussion.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e133" href="#d0e133" id=
"ftn.d0e133">2</a>]</sup> The ECMA spec also notes: &quot;<span class=
"quote">The closest equivalent of a delegate in C or C++ is a
function pointer, but whereas a function pointer can only reference
static functions, a delegate can reference both static and instance
methods. In the latter case, the delegate stores not only a
refreence to the method's entry point, but also a reference to the
object instance on which to invoke the method.</span>&quot;</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e190" href="#d0e190" id=
"ftn.d0e190">3</a>]</sup> Error handling omitted for brevity.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e210" href="#d0e210" id=
"ftn.d0e210">4</a>]</sup> Read-only fields are used instead of the
'better practice' properties purely to minimise code bloat.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e272" href="#d0e272" id=
"ftn.d0e272">5</a>]</sup> Although not central to this discussion,
it is worth mentioning the FCL System.Data.DataSet class. An object
of this class is an in-memory cache of data retrieved from a
database, and greatly simpilfies data retrieval andupdate
operations. Strongly-typed datasets can be used, whose class
definitions are created from XML Schema [<a href="#Auto">Auto</a>],
allowing compile-type type-checking of dataset operations, and
access to tables and columns by name, instead of collections and
indices.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e294" href="#d0e294" id=
"ftn.d0e294">6</a>]</sup> In some respects, the plumbing required
for transactions of this kind is akin to some of the problems
addressed by Aspect-Oriented Programming [<a href="#AOP">AOP</a>],
although such issues are beyond the scope of this article.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
