Friday, June 24, 2011

Castle Windsor

Castle Windsor

Castle Windsor is an inversion of control container. It's built on top of a MicroKernel responsible for inspecting the classes and trying to understand what they need in order to work and then provide the requirements or fail fast if something is wrong.

For our small example, the following code will take care of everything:

IWindsorContainer container = new WindsorContainer();
container.AddComponent( "newsletter", typeof(INewsletterService),
typeof(SimpleNewsletterService) );
container.AddComponent( "smtpemailsender", typeof(IEmailSender),
typeof(SmtpEmailSender) );
container.AddComponent( "templateengine", typeof(ITemplateEngine),
typeof(NVelocityTemplateEngine) );

// Ok, Lets start Now...
INewsletterService service = (INewsletterService) container["newsletter"];
service.Dispatch("hammett at gmail dot com", friendsList, "merryxmas");

First, let me explain what happened in this code snippet:

1. You registered the service INewsletterService on the container and you also said that the class SimpleNewsletterService contains an implementation of INewsletterService. The first argument is a key that you use to request this service later. You might also request the service by the Type.
2. Windsor inspected the implementation you provided and noticed that it requires two other services to work. It checked itself and realized that it doesn't have such services registered, so if somebody requests the INewsletterService service instance, it will throw an exception.
3. You registered the service IEmailSender. Windsor notices that the implementation has just one public constructor that receives two arguments (host and port). It's not able to satisfy this configuration as we haven't provided an external configuration. We'll fix that later.
4. You registered the service ITemplateEngine. Windsor registers it successfully and shouts to other components in a WaitingDependency state that a component has been registered. The INewsletterService realizes that one of its dependencies is OK to go, but it still is waiting for the other.

The fact that a class has a non default constructor has a specific meaning for the container. The constructor says to it: "Look, I really need these in order to work". If our implementation were different, the container would have used a different approach. For example:


public class SmtpEmailSender : IEmailSender
{
private String _host;
private int _port;

public SmtpEmailSender()
{
_host = "mydefaulthost";
_port = 110; // default port

}

public String Host
{
get { return _host; }
set { _host = value; }
}

public int Port
{
get { return _port; }
set { _port = value; }
}

...
}

In this case, you may or may not specify the host and port in an external configuration and the container will be able to use it. Another approach is to expose more than one constructor. The container will try to use the best constructor - meaning the one it can satisfy more arguments.

"But wait! What about the configuration?"

By default, Windsor will try to obtain the component configuration from the XML file associated with the AppDomain. However, you can override it by implementing the interface IConfigurationStore. There's another implementation of IConfigurationStore that reads the configuration from standard XML files, which is good when you have a configuration for testing environment, another for production, and so on.

Here is the configuration file you must use to run the example:

sample configuration file




From experience, I know that sometimes it's dumb to have interfaces for all your components. There are classes that are unlikely to have a different implementation, like Data Access Objects. In this case, you can register classes into the container as follows:

public class MyComponent
{
private IEmailSender _sender;

public MyComponent()
{
}

public IEmailSender EmailSender
{
get { return _sender; }
set { _sender = value; }
}
}

IWindsorContainer container = new WindsorContainer();
container.AddComponent( "mycomponent", typeof(MyComponent) );

You might want to request a component by the service:


IEmailSender emailSender = container[ typeof(IEmailSender) ] as IEmailSender;

But please note that you can register more than one implementation for a given service. The default behavior is to return the first implementation registered for the specified service. If you want a specific implementation, then you need to use the key.

As a matter of fact, the last paragraph leads us to an interesting situation. Suppose you have implemented several IEmailSender but you want that the INewsletterService implementation uses the SMTP version and nothing else. The better way to do it is to use the configuration to specify the exact implementation you want:






The nodes inside 'parameters' must use the name of a property exposed by the implementation or the name of the argument the implementation's constructor uses. Just to refresh your memory:


public class SimpleNewsletterService : INewsletterService
{
private IEmailSender _sender;
private ITemplateEngine _templateEngine;

public SimpleNewsletterService(IEmailSender sender, ITemplateEngine templateEngine)
{
_sender = sender;
_templateEngine = templateEngine;
}

Friday, June 10, 2011

Search in a generic list

SomeObject desiredObject = myObjects.Find( o => o.Id == desiredId);

Tuesday, July 20, 2010

Database Transaction.


What are Transactions? 

A transaction symbolizes code or a set of components or procedures which must be executed as a unit. All the methods must execute successfully or the complete unit fails. A transaction can be described to cover the ACID properties for mission critical applications. 

What are the ACID Properties?

1.    Atomicity
2.    Consistency
3.    Isolation
4.    Durability

Transfer Funds Sample 

We will build a sample ASP.NET web form for a fictitious bank which will transfer a specified amount from one account to another - if the  balance in the first account is sufficient to cover the transfer. 
First we need to create the database we will using in the example.
I used an MS Access database containing only one table : tblAccount.
 
Field Name
Field Type
AccNumber
Text
dBalance
Double
Listing 1 displays the code for the web page. Save the web page as Test.aspx.
First include the Namespaces required for accessing the data. 
 Import Namespace="System.Data"
 Import Namespace="System.Data.OleDb"
Here is the function which processes the transaction for transferring the data.
For this example we assume that the transaction should be rolled back (Cancelled) if :
1.    There are insufficient funds in the From Account to cover the transfer. 
2.    Either of the SQL statements for marking credit or debit in the To and From accounts results in an error. 
We create the Connection needed to connect to our database.
OleDbConnection Conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=c:\\inetpub\\wwwroot\\dotnet\\test.mdb;");
In real life we would use Server.MapPath to map to the location of the database. 
We use the Data Reader oReader to check the validity of the amount in the From Account. The crux of the function is to execute the two SQL queries one to subtract the amount from the From Account and one to add the same amount to the balance in the To Account. 
We start the transaction after we have created the data objects .The transaction should be kept as short as possible to avoid concurrency issues and to enable maximum number of positive commits.

Create the transaction and associate the transaction with the OleDbCommand as follows: 
OleDbTransaction Trans = Conn.BeginTransaction(IsolationLevel.ReadCommitted);
cmd.Transaction = Trans;
Within the Try block run the transaction and Commit the transaction if everything proceeds smoothly. Committing a transaction will write the changes to the database. 
If there is an exception we will Roll Back the transaction. This will cancel any changes that have been carried out as a part of the transaction. This is how we maintain the integrity of our transaction.
try
{
    oReader = cmd.ExecuteReader();
    oReader.Read();
    dCurrBalance = oReader.GetDouble(0);
    oReader.Close();
    if (dCurrBalance < Convert.ToDouble(txtAmt.Text))
    {
        throw (new Exception("Insufficient funds for transfer"));
    }
    strSQL = "Update tblAccount set dbalance =  dBalance - " + txtAmt.Text + " where AccNumber = '" +
    txtFrom.Text + "'";
    cmd.CommandText = strSQL;
    cmd.ExecuteNonQuery();
    strSQL = "Update tblAccount set dbalance =  dBalance + " + txtAmt.Text + " where AccNumber = '" +
    txtTo.Text + "'";
    cmd.CommandText = strSQL;
    cmd.ExecuteNonQuery();
    Trans.Commit();
    lbl.Text = "true";
}
catch (Exception ex)
{
    Trans.Rollback();
    lbl.Text = "Error: " + ex.Message;
}
finally
{
    Conn.Close();
}
Note how we Throw an exception if the balance in the From Account is less than the transfer amount. 
throw (new Exception("Insufficient funds for transfer")); 
The string passed in the constructor of the Exception object initializes the message for the Exception that will be raised.
Finally we indicate the results of the transfer activity to the user .
lbl.Text = "Fund Transfer of Amount " + txtAmt.Text + " from Account " + txtFrom.Text + " to Account " + txtTo.Text + " was executed successfully.";
OR
lbl.Text = "Error: " + ex.Message;
 
In real life, we would have converted the error message to a more meaningful and user friendly message. 
Here is the complete code listing for the web form.

Listing 1: Test.aspx : Transfer Funds Web Page. 
Import Namespace="System.Data"
Import Namespace="System.Data.OleDb"
<html>
<head>
    <title>Transfer Fundstitle>

    <script language="C#" runat="server">
        protected void TransferFund(Object Sender, EventArgs e)
        {
            String strSQL = "Select dBalance FROM tblAccount where AccNumber='" + txtFrom.Text + "'";
            double dCurrBalance;
            OleDbConnection Conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA
            SOURCE=c:\\inetpub\\wwwroot\\dotnet\\test.mdb;");
            Conn.Open();
            OleDbDataReader oReader;
            OleDbCommand cmd = new OleDbCommand(strSQL, Conn);
            OleDbTransaction Trans = Conn.BeginTransaction(IsolationLevel.ReadCommitted);
            cmd.Transaction = Trans;
            try
            {
                oReader = cmd.ExecuteReader();
                oReader.Read();
                dCurrBalance = oReader.GetDouble(0);
                oReader.Close();
                if (dCurrBalance < Convert.ToDouble(txtAmt.Text))
                {
                    throw (new Exception("Insufficient funds for transfer"));
                }
                strSQL = "Update tblAccount set dbalance =  dBalance - " + txtAmt.Text + " where AccNumber = '"
                + txtFrom.Text + "'";
                cmd.CommandText = strSQL;
                cmd.ExecuteNonQuery();
                strSQL = "Update tblAccount set dbalance =  dBalance + " + txtAmt.Text + " where AccNumber = '"
                + txtTo.Text + "'";
                cmd.CommandText = strSQL;
                cmd.ExecuteNonQuery();
                Trans.Commit();
                lbl.Text = "true";
            }
            catch (Exception ex)
            {
                Trans.Rollback();
                lbl.Text = "Error: " + ex.Message;
            }
            finally
            {
                Conn.Close();
            } 
        } 
 
    script>

head>
<body>
    <form id="frmTransfer" runat="server">
        <asp:Label ID="lblFrom" runat="server">Enter the account number from which to transfer
          fundsasp:Label>
        <asp:TextBox ID="txtFrom" runat="server">asp:TextBox><br />
        <asp:Label ID="lblTo" runat="server">Enter the account number to which to transfer fundsasp:Label>
        <asp:TextBox ID="txtTo" runat="server">asp:TextBox><br />
        <asp:Label ID="lblAmount" runat="server">Enter the amount to transferasp:Label>
        <asp:TextBox ID="txtAmt" runat="server">asp:TextBox><br />
        <asp:Button ID="Button1" OnClick="TransferFund" runat="server" Text="Start Transfer">
        asp:Button><br />
        <asp:Label ID="lbl" runat="server">asp:Label>
    form>
body>
html>
Figure 1 : Front end web page for the transaction example.
Figure 2 : Successfully Committed Transactions.
Figure 3: Insufficient Funds RollBack !  


Note:  When the transaction is rolled back (Insufficient funds or an error in the SQL statements) the Balance field in both the From Account and To Account in the database is not updated.



New transaction model addresses shortcomings
The Microsoft .NET 2.0 platform introduces a new namespace called System.Transactions that brings in a lightweight, simplified transaction model. This article discusses the shortcomings of current transaction models and introduces System.Transactions for .NET Framework 2.0 beta 2.
Currently there are two transaction models available in the .NET world, both of which are suited for certain situations. The first is part of the rich ADO.NET data providers. The second is the enterprise services transaction. Before we examine System.Transactions, let’s have a look at the current models.
The ADO.NET transaction model
The transaction handling model available as part of the .NET data providers is very simple. A general update statement might consist of the following steps:
C# Code
SqlConnection con = new SqlConnection("Connection String");

SqlTransaction tr = con.BeginTransaction();

SqlCommand cmd = new SqlCommand("Update Account set Balance=500 where AccountId=52",
 con, tr);

try

{

cmd.ExecuteNonQuery();

tr.Commit();

}

catch (Exception exc)

{

tr.Rollback();

}

finally

{

con.Close();

}
We created a transaction with the connection object and associated the transaction objects with the command objects. After executing the commands, we specified whether the transaction should commit or rollback. If there is an exception, we select a rollback, and if not, we are committing the transaction.
Though the ADO.NET transaction seems like a good model, there are a few problems associated with it. One of the biggest drawbacks occurs when you have updates for more than one database or resource grouped under a single transaction. As you can see in the previous code block, the transaction object is actually created from a connection to a single database. So there is no direct way of grouping updates to more than one database into a single transaction.
Also, when you manage transactions in an object-oriented scenario, database transactions are not ideal. In an object-oriented environment, many objects (such as customer, invoice number, etc.) coordinate together to complete a business process. If the business process is transactional, the transaction object might need to be passed around or there might be additional code involved to create a layer to manage the process.
Enterprise services transactions
Enterprise services transactions address most of the shortcomings of the ADO.NET transactions by providing a two-phase commit protocol and a distributed transaction manager. These two features enable you to have transactions independent of the database, and provide transactions in a declarative manner.
The following code shows a simple AccountManager class that accepts two accounts and performs a transfer between the two. The transfer is completed by depositing cash into one account and withdrawing cash from the other, with each method separately updating the balances of the accounts in the database. If any of these methods generates an error, the entire transfer method will be rolled back.
C# Code
[Transaction(TransactionOption.Required)]

class AccountManager : ServicedComponent

{

[AutoComplete()]

void TransferCash(Account from, Account to, double amt)

{

from.Withdraw(amt);

to.Deposit(amt);

}

}
If you look at the above code block, we are not explicitly creating any transaction objects. We are using declarative transactions to mark areas where transactions will be used. The Autocomplete attribute specifies that the transaction should be commited if no errors are generated. The Transaction attribute paired with TransactionOption.Required specifies that the objects we create from AccountManager will be transactional and will always run under a transaction.
With this model, you can access more than one resource and enlist them in one transaction. In the above code, for example, the withdrawal method can update one database and the deposit method can update another database.
But there are still a few problems in this model. First, your class needs to inherit from the ServicedComponent class to take advantage of enterprise service transactions. With the single inheritance model, most .NET languages will restrict your class from inheriting from any other base class.
Another drawback is that enterprise service transactions are always taken as a distributed transaction. Even if you are using a single database, enterprise services will still take it as a distributed transaction and handle it as such. As a result, you might end up using more resources than needed.
Another problem is that the components you create need to be deployed in component services to run under the COM+ context. Though .NET simplifies this deployment a great deal, you still need to place a strong name for the assembly with serviced components and make sure the settings for the components are set properly.
Introducing System.Transactions
The System.Transactions model is a new addition to the .NET 2.0 framework. It addresses the shortcomings in the above discussed models, and brings the best features of the ADO.NET and enterprise services transaction models together.
In System.Transactions, you have the TransactionScope object you can use to scope a set of statements and group them under one transaction. The following System.Transactions model generates the same transaction we saw in the enterprise services example.
C# Code
class AccountManager

{

void TransferCash(Account from, Account to, double amt)

{

using(TransactionScope scope=new TransactionScope())

{

from.Withdraw(amt);

to.Deposit(amt);

scope.Complete();

}

}

}
If you look at the above code, our class is not inheriting any base classes to enable transactions. All we are doing is using a TransactionScope object and wrapping the method calls accessing the database with a using block. Once complete, we are setting the scope to complete and indicating the transaction should commit now. But what if the withdrawal method creates an exception? Then the complete method for the scope will not be called and the transaction will be rolled back.
System.Transactions has the unique capability of knowing whether to use a distributed transaction or not. It will use a lightweight transaction if there is a single domain accessing a single database, or it will use a distributed transaction similar to the enterprise services transaction model if there are multiple databases to access.
In most scenarios, you will interact with the TransactionScope object for your transaction handling work. You can even nest transaction scopes and provide transaction options to specify how each of the blocks interact with each other. Below we have a method to log successful withdrawals and we need to make sure this method will attach itself to a root transaction if it exists or spawn a new transaction otherwise:
C# Code
void LogWithdrawals(Account account,double amt)

{

using (TransactionScope scope = 
new TransactionScope (TransactionScopeOption.Required))

{

//database calls to log details

}

 

}
In the above code, we have created a transaction scope option with the value Required. This is used to specify that the block of code should always be within a transaction. If there is an existing transaction, the scope within LogWithdrawals will join with the root transaction; otherwise it will create a new one. The other transaction scope options available are RequiresNew (will always create a new transaction) and Suppress (will never be part of a transaction). These options can be used to change the way nested transactions will participate in the overall transaction.
You can also adorn a transaction scope with a TransactionOption object to specify the isolation level and the timeout period of the transaction. For example:
C# Code
TransactionOptions options = new TransactionOptions();

options.IsolationLevel = IsolationLevel.ReadCommitted;

options.Timeout = new TimeSpan(0, 1, 0);

using (TransactionScope scope = new TransactionScope
(TransactionScopeOption.RequiresNew,options))

{

//code within transaction

}
The above code sets our transaction scope to use an isolation level of read committed; we have also set a timeout of one minute for our transaction.

15 Seconds : Transaction Processing in ADO.NET 2.0
 



It seems like just yesterday that Microsoft introduced a brand new data access technology that brought a ton of power as well as a decent sized learning curve. When ADO 2.xxx turned into ADO.NET, things changed dramatically. It took some getting used to to feel comfortable using the whole 'disconnected' model, but the "cool" factor made it all worth while. When .NET Framework 1.1 came out, very little changed in regard to what you needed to learn or what you could do with it. Well, we're turning another corner and right off in the distance is ADO.NET 2.0. The differences between ADO.NET 2.0 and < ADO.NET 2.0 are pretty profound, and you'll definitely have to spend some time learning new features if you want to take advantage of its power. I think you'll find that it's well worth the effort.
So you're probably thinking "Oh wow, big deal, new features available in a new release of the product, I never would have guessed." Well, there's a lot of cool new features all over the place, too much to discuss in a single article, but one area that really stands out is transaction processing. To say that there's a lot of bang for the buck would be a real understatement, and if you've had to work extensively with transactions, both local and/or distributed in the past, I think you'll really be impressed with what Microsoft has done.
Transactions
One of the more significant areas of improvement is in transaction processing. It's still early in beta so nothing is written in stone, but by and large things got a LOT easier. In the original versions of ADO.NET, you could implement transactions a few different ways. If your implementation context was a single database, you could instantiate an instance of one of the IDBTransaction objects, attach it to your connection, process what you wanted, and either commit or rollback depending on the results. By virtue of the fact that this was done client side, many people found that it wasn't all that they were hoping. A similar method would entail rolling your transaction processing into a stored procedure and simply invoking the procedure. On the whole I think this produced some more reliable results, but it had some problems too - namely that it was highly coupled with the specific database implementation you were using. So if you needed to move a file for instance, send a success message to a MSMQ Message Queue, and then update a SQL Server database, you were going to have to do a fair amount of work. This process has been simplified so much it's hard to believe it actually works. Anyway, I'll dive into an example in a second, but let me make sure that the distinction I'm about to draw is clear: Now, just as before, you have two choices with regard to transactions, Local and Distributed. Distributed transactions span multiple items whereas local transactions typically span just one. Either way you can take advantage of the TransactionScope object to simplify your life.
Simple Transaction Under ADO.NET 2.0:
 
bool IsConsistent = false;
using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
{
      SqlConnection cn = newSqlConnection(CONNECTION_STRING );
      string sql = "DELETE Categories";
      SqlCommand cmd = newSqlCommand(sql, cn);
      cn.Open();
      cmd.ExecuteNonQuery();
      cn.Close();
            //Based on this property the transaction will commit if
            //successful.  If it fails however, this property will
            //not be set and the transaction will not commit.
      ts.Consistent = IsConsistent;
}
Basically, I created a query which whacked and entire table, wrapped it in a transaction and ensured that it wouldn't commit. In doing so, the table remains fully in tact just as it was before calling ExcecutNonQuery. Now, what's so different about this? Well, notice that the connection itself is confined within the scope so it automatically participates in the transaction. All that is required to commit or rollback the transaction is specifying True or False for consistent. A more realistic example can be illustrated by making a few minor changes: 





A Slightly Improved Implementation:
 
bool IsConsistent = false;
using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
{
     SqlConnection cn = newSqlConnection(CONNECTION_STRING );
     string sql = "DELETE Categories";
     SqlCommand cmd = newSqlCommand(sql, cn);
     cn.Open();
     try
     {
          cmd.ExecuteNonQuery();
          IsConsistent = true;
     }
     catch (SqlException ex)
     {
         //You can specify additional error handling here
     }
     cn.Close();
     //Again, since this was set to false originally it will only
     //commit if it worked.
     ts.Consistent = IsConsitent;
}
This example is more in line with the earlier version of ADO.NET's transaction processing, namely, if everything works then commit, else rollback. This is hardly climactic in any practical sense because even though it's a lot more concise than previous versions, you're not really talking about any dramatic reduction in complexity of code. To see the elegance and power of this object you really need to examine a distributed scenario. Say that you have some really complex situation where you have a table in a Yukon database that you want to clear, and then you have a corresponding table in a separate database that needs to be cleared as well. Furthermore, assume that this is an all or nothing deal and there has to be complete success or complete failure.
bool IsConsistent = false;
using (TransactionScope ts = newTransactionScope())
{
  using (SqlConnection cn = newSqlConnection(YUKON_CONNECTION_STRING))
  {
    string sql = "DELETE Products";
    SqlCommand cmd = newSqlCommand(sql, cn);
    cn.Open();
    try
    {
       cmd.ExecuteNonQuery();
       using(SqlConnection cnn = newSqlConnection(CONNECTION_STRING))
       {
            string sql_2 = "DELETE Categories";
            SqlCommand cmd2 = newSqlCommand(sql_2, cnn);
            cnn.Open();
            cmd.ExecuteNonQuery();
            cnn.Close();
       }
           IsConsistent = true;
     }
     catch (SqlException ex)
     {
        //You can specify additional error handling here
     }
     cn.Close();
  }
  ts.Consistent = IsConsistent;
}
Now, what I'm about to discuss is pretty amazing, and I can't in clear conscience take credit for it. Angel Saenz-Badillos was the first one to tip me off to how all of this works and worked with me through a few examples. It's laughable at the moment, but the first time I heard of this, my initial response was something like "Ok, that'll save me 3 lines of code - great" I couldn't believe that it could possibly live up to the hype, and it took working with it a few times before my little brain could process it.
So here's the deal stated simply. Wrap everything in a TransactionScope object, and it takes care of everything else for you. What does that mean? Well, it will determine if you need a local or a distributed transaction, and it will react accordingly. It will enlist where necessary and process locally otherwise. Notice that the first connection string points to a Yukon (SQL Server 2005) database. As such, you can take advantage of "Delegation". This is a fancy way of saying "We don't need no stinking distributed transaction, we're using Yukon" and thereafter not using it unless it becomes necessary. Now, if you cut out the inner statements where you fire the query pointing to ANOTHER database, everything would be done under the purview of a local transaction. However, as soon as we try to hit another database, we're back in distributed transaction mode. Now, the natural assumption is that they are run under two different contexts, right? After all, you need to promote to DT mode once you try to hit the second database, but prior to that you were running locally. Actually, the answer is NO, you don't need to do squat. That's what's so amazing about it. As soon as the code gets to a point where it won't be running locally, everything is promoted accordingly. And you don't just have support for SQL Server here - Oracle and MSMQ are both currently supported, and there's a REALLY strong probability that File System support will be included in the final release.
So, does the same principle apply here if you were connecting to Oracle or MSMQ instead of SQL Server 2000? Yes, and for all intents and purposes the transactional component here would behave identically. If you've used COM+ before, then you no doubt realize how much easier this is. If you haven't, just put in Distributed Transaction COM+ into Google or read up on it, and you'll quickly see how much more simple this makes things. Even if you aren't familiar with either of those scenarios, just look to the unstable nature of client side transaction processing with ADO.NET and you'll quickly see this is pretty darned impressive.
As cool as this is, there's no doubt some folks out there won't be impressed. Well, fine. You aren't precluded from doing anything you otherwise would by employing the TransactionScope; heck you don't even have to use it. If you like writing tons of code, and you get a sense of security by doing unnecessary tasks, knock yourself out. Or even if you're not that much of a hard-core ludite, but you want to do things manually, here's how you do it:
Client Side Transaction under 1.x Framework
privatebool OldSchool()
{
  bool IsConsistent = false;
  ICommittableTransaction oldSchoolTrans = Transaction.Create();
  using (SqlConnection cn = newSqlConnection(CONNECTION_STRING))
  {
                string sql = "DELETE Categories";
                SqlCommand cmd = newSqlCommand(sql, cn);
                cn.Open();
                cn.EnlistTransaction((ITransaction)oldSchoolTrans);
                try
                {
                    cmd.ExecuteNonQuery();
                    IsConsistent = true;
                    returntrue;
                }
                catch (SqlException ex)
                {
                    //You can specify additional error handling here
                                      //This is where you’d rollback your transaction
                    return (ex.ToString().Length < 1);
                }
                cn.Close();
      }
  }



Transactions with .NET 2.0
One disadvantage of automatic transactions with serviced components is that these transactions always make use of the DTC, even when local transactions would be enough. Of course, using DTC is more expensive than a local programmatic transaction as was used in Listing 7-2.
With .NET 2.0, a new assembly System.Transactions will be available that includes some new classes dealing with transactions. Particularly worth mentioning are the classes Transaction, TransactionScope, and TransactionManager. These classes are in the namespace System.Transactions. The big advantage of these classes is that the new transaction services know about local and DTC transaction and will support the Web services standard WS-AtomicTransaction6 in the future. Depending on the scope of the transaction, the fastest possible technology is used.
Listing 7-11 shows one way to create transactions with .NET 2.0.7 Creating and disposing of a TransactionScope object defines a transactional code block. With the constructor of the TransactionScope object and the TransactionScopeOption enumeration, you can define whether a new transaction is required or whether a transaction that already exists from the outer block should be used. With the parameter of type EnterpriseServicesInteropOption, you can specify the interaction with COM+ contexts. The method Complete() indicates that all operations within the scope of the transaction have been successful. At the end of the using statement (where the Dispose() method gets called), the transaction outcome of the block is defined. If the Complete method was not called because an exception occurred, the transaction is aborted. If the scope of the transaction was successful, the transaction is committed if it is a root transaction. If the scope is not the root of the transaction, the outcome of the transaction is influenced.
Listing 7-11 Programming Transactions with .NET 2.0
using System;
using System.Transactions;
using Samples.Courses.Entities;
using Samples.Courses.Data;
class TxDemo
{
  static void Main()
  {
    using (TransactionScope scope = new TransactionScope(
      TransactionScopeOption.Required))
    {
      Course c = new Course();
      c.Number = "MS-2557";
      c.Title = ".NET Enterprise Services";
      c.Active = true;
      CourseData db = new CourseData(connectionString);
      db.AddCourse(c);
      scope.Complete();
    }
}
With Indigo Services, you may declare transactions, as shown in Listing 7-12. This should look similar to the declarative transactions of the serviced components model. The attribute [OperationContract(TransactionFlowAllowed=true)] defines that a transaction is created. The attribute [OperationBehavior(Auto- EnlistTransaction=true)] defines that the transaction is automatically enlisted with the transaction coordinator.
Listing 7-12 Declaring Transactions with Indigo Services
[ServiceContract]
[ServiceBehavior(InstanceMode=InstanceMode.PerCall)]
public interface IDemoService
{
  [OperationContract(TransactionFlowAllowed=true)]
  [OperationBehavior(AutoEnlistTransaction=true)]
  void AddCourse(Course course);
}

[BindingRequirements(
  TransactionFlowRequirements = RequirementsMode.Require,
  QueuedDeliveryRequirements = RequirementsMode.Disallow,
  RequireOrderedDelivery = true
  )]
public class DemoService : IDemoService
{
  public void AddCourse(Course course)
  {
    //...
  }
}








Introduction:
A transaction is a unit of work. You use transactions to ensure the consistency and integrity of a database. If a transaction is successful, all of the data modifications performed during the transaction are committed and made permanent. If an error occurs during a transaction, you can roll back the transaction to undo the data modifications that occurred during the transaction.

This article describes how to manage distributed transactions that can span multiple data sources in a Microsoft .NET application.
Distributed Transactions:
A distributed transaction spans multiple data sources. Distributed transactions enable you to incorporate several distinct operations, which occur on different systems, into an atomic action that either succeeds or fails completely.
Properties of a transaction:
  • Atomicity:
    A transaction is an atomic unit of work, an indivisible set of operations. The operations that you perform within a transaction usually share a common purpose, and are interdependent. Either all of the operations in a transaction should complete, or none of them should. Atomicity helps to avoid data inconsistencies by eliminating the chance of processing a subset of operations.
  • Consistency:
    A transaction preserves the consistency of data. A transaction transforms one consistent state of data into another consistent state of data. Some of the responsibility for maintaining consistency falls to the application developer, who must ensure that the application enforces all known integrity constraints.
  • Isolation:
    A transaction is a unit of isolation. Isolation requires that each transaction appear to be the only transaction manipulating the data store, even though other transactions might be running concurrently. Transactions attain the highest level of isolation when they have the ability to be serialized; at this level of isolation, the results obtained from a set of concurrent transactions are identical to the results obtained by running each transaction serially. A high degree of isolation can limit the number of concurrent transactions, and consequently, applications often reduce the isolation level in exchange for better throughput.
  • Durability:
    A transaction is the unit of recovery for a set of operations. If a transaction succeeds, the system guarantees that its updates will persist, even if the computer crashes immediately after the application performs a commit operation. Specialized logging allows the system restart procedure to complete unfinished operations so that the transaction is durable.
Creating Distributed Transactions:
The .NET Framework 2.0 includes the System.Transactions namespace, which provides extensive support for distributed transactions across a range of transaction managers, including data sources and message queues. The System.Transactions namespace defines the TransactionScope class, which enables you to create and manage distributed transactions.
To create and use distributed transactions, create a TransactionScope object, and specify whether you want to create a new transaction context or enlist in an existing transaction context. You can also exclude operations from a transaction context if appropriate.
You can open multiple database connections within the same transaction scope. The transaction scope decides whether to create a local transaction or a distributed transaction. The transaction scope, automatically promotes a local transaction to a distributed transaction if necessary, based on the following rules:
  • When you create a TransactionScope object, it initially creates a local, lightweight transaction. Lightweight transactions are more efficient than distributed transactions because they do not incur
    the overhead of the Microsoft Distributed Transaction Coordinator (DTC).
  • If the first connection that you open in a transaction scope is to a SQL Server 2005 database, the connection enlists in the local transaction. The resource manager for SQL Server 2005 works with
    the System.Transactions namespace and supports automatic promotion of local transactions to distributed transactions. Therefore, the transaction scope is able to defer creating a distributed
    transaction unless and until it becomes necessary later.
  • If the first connection that you open in a transaction scope is to anything other than a SQL Server 2005 database, the transaction scope promotes the local transaction to a distributed transaction
    immediately. This immediate promotion occurs because the resource managers for these other databases do not support automatic promotion of local transactions to distributed transactions.
  • When you open subsequent connections in the transaction scope, the transaction scope promotes the transaction to a distributed transaction, regardless of the type of the database.
Steps of creating distributed transaction:
1.    Instantiate a TransactionScope object.
2.    Open a connection with the database.
3.    Perform your database operations (insert, update & delete).
4.    If your operations completed successfully, mark your transaction as complete.
5.    Dispose The TransactionScope object.
If all the update operations succeed in a transaction scope, call the Complete method on the TransactionScope object to indicate that the transaction completed successfully. To terminate a transaction, call the Dispose method on the TransactionScope object. When you dispose a TransactionScope, the transaction is either committed or rolled back, depending on whether you called the Complete method:
  • If you called the Complete method on the TransactionScope object before its disposal, the transaction manager commits the transaction.
  • If you did not call the Complete method on the TransactionScope object before its disposal, the transaction manager rolls back the transaction.
TransactionScope How To:
A transaction scope defines a block of code that participates in a transaction. If the code block completes successfully, the transaction manager commits the transaction. Otherwise, the transaction manager rolls back the transaction. Bellow is a guide lines on how you can create and use a TransactionScope instance:
1.    Add a reference to the System.Transactions assembly.
2.    Import the System.Transactions namespace into your application.
3.    If you want to specify the nesting behavior for the transaction, declare a TransactionScopeOption variable, and assign it a suitable value.
4.    If you want to specify the isolation level or timeout for the transaction, create a TransactionOptions instance, and set its IsolationLevel and TimeOut properties.
5.    Create a new TransactionScope object in a using statement (a Using statement in Microsoft Visual Basic).
Pass a TransactionScopeOption variable and a TransactionOptions object into the constructor, if appropriate.
6.    In the using block (Using block in Visual Basic), open connections to each database that you need to update, and perform update operations as required by your application. If all updates succeed, call the Complete method on the TransactionScope object
7.    Close the using block (Using block in Visual Basic) to dispose the TransactionScope object. If the transaction completed successfully, the transaction manager commits the transaction. Otherwise, the transaction manager rolls back the transaction.


Listing 1: TransactionScope C#:
using System.Transactions;
...
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
options.Timeout = new TimeSpan(0, 2, 0);
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
            using (SqlConnection connA = new SqlConnection(connStringA))
{
                        using (SqlCommand cmdA = new SqlCommand(sqlStmtA, connA))
                        {
                                    int rowsAffectedA = cmdA.ExecuteNonQuery();
                                    if (rowsAffectedA > 0)
                                    {
                                                using (SqlConnection connB = new SqlConnection(connStringB))
                                                {
                                                            using (SqlCommand cmdB = new SqlCommand(sqlStmtB, connB))
                                                            {
                                                                        int rowsAffectedB = cmdB.ExecuteNonQuery();
                                                                        if (rowsAffectedB > 0)
                                                                        {
                                                                                    transactionScope.Complete();
                                                                        }
                                                            } // Dispose the second command object.
                                                } // Dispose (close) the second connection.
                                    }
                        } // Dispose the first command object.
            } // Dispose (close) the first connection.
} // Dispose TransactionScope object, to commit or rollback transaction.
Listing 2: TransactionScope VB.NET:
Imports System.Transactions
...
Dim options As New TransactionOptions()
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted
options.Timeout = New TimeSpan(0, 2, 0)
Using scope As New TransactionScope(TransactionScopeOption.Required, options)
Using connA As New SqlConnection(connStringA)
Using cmdA As New SqlCommand(sqlStmtA, connA)
Dim rowsAffectedA As Integer = cmdA.ExecuteNonQuery()   
            If (rowsAffectedA > 0) Then
Using connB As New SqlConnection(connStringB)
Using cmdB As New SqlCommand(sqlStmtA, connB)
Dim rowsAffectedB As Integer = cmdB.ExecuteNonQuery()
If (rowsAffectedB > 0) Then
transactionScope.Complete()
End If
End Using ' Dispose the second command object.
End Using ' Dispose (close) the second connection.
End If
End Using ' Dispose the first command object.
End Using ' Dispose (close) the first connection.
End Using ' Dispose TransactionScope object, to commit or rollback transaction.