Writing an Atomic transaction is easy in .NET. First I
created a Class Library project and then created a MyTransaction class to
implement my logic in it.
MyTransaction has a Transfer() method that gets the
identifier of an account, the integer value to add to that account and database
connection string. This method tries to add the value to the specific account
in an Atomic transaction. I produced an exception in this transaction to show
what would happen if a value was not valid according to the sample
constraints. I threw this exception in after successfully adding a value to an
account.
What I did to build my Class Library project was to add a
reference to System.EnterpriseServices, inherited my class from
ServicesComponent base class and called ContextUtil.SetComplete() method at the
end of my Atomic transaction.
Figure 2
So initially my class looked like this:
Listing 2
using System;
using System.Collections.Generic;
using System.Text;
using System.EnterpriseServices;
using System.Data;
using System.Data.SqlClient;
namespace AtomicTransactions
{
public class MyTransaction : ServicedComponent
{
Note that I cannot provide a public default constructor for
this class because later I cannot register it as COM+ component service.
Below is the logic for the Transaction() method. After
adding the value to database, I checked a constraint and threw the exception if
the value was not between 0 and 10. This is a sample constraint to show the
result in test stages.
Listing 3
public void Transfer(int accountID, int value,
string connectionString)
{
try
{
AddValue(accountID, value, connectionString);
if ((value < 0) || (value > 10))
throw new
ArgumentException("Value isn't valid!");
// Atomic transaction ends here
ContextUtil.SetComplete();
}
catch (Exception ex)
{
throw new Exception
("An error occurred in our transaction");
}
}
Simple logic for AddValue() method is:
Listing 4
private void AddValue(int id, int value,
string connectionString)
{
try
{
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand("AddToAccount", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("id", id);
command.Parameters.AddWithValue("value", value);
connection.Open();
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw ex;
}
}