Rico Suter's blog.
 


First, I’ll show an example of the correct usage of an Entity Framework’s ObjectContext. At the beginning of the usage block, the ObjectContext is created; at the end it will be disposed (see using-Keyword).

using (var ctx = new MyObjectContext()) {
    // do your stuff
    ctx.SaveChanges();
}

Usually the code in the using block is not a whole transaction. The call of the method SaveChanges opens a new database connection, starts a new transaction, writes all changes and commits the transaction if no problems occurred. Every call of SaveChanges has its own transaction. If you want to call the SaveChanges method multiple times but in only one transaction, you have to manage the transaction manually.

The following extension method helps opening a connection and handling a transaction:

public static class ObjectContextExtensions
{
    public static void DoTransaction(this ObjectContext context, Action<DbTransaction> action)
    {
        DoTransaction(context, false, action);
    }

    public static void DoTransaction(this ObjectContext context, bool manualCommit, Action<DbTransaction> action)
    {
        context.Connection.Open();
        try
        {
            using (var tx = context.Connection.BeginTransaction())
            {
                try
                {
                    action(tx);
                    if (!manualCommit)
                        tx.Commit();
                }
                catch
                {
                    tx.Rollback();
                    throw; 
                }
            }
        }
        finally
        {
            context.Connection.Close();
        }
    }
}

This extension method can be used as follows:

using (var ctx = new MyObjectContext() 
{
    ctx.DoTransaction(tx => 
    {
        // do your stuff
        ctx.SaveChanges();
    }); 
}

There is an other approach to manage transactions. With the TransactionScope class it is easier to create a transaction. This way the application doesn’t create a SqlTransaction but a DistributedTransaction which can work over multiple ObjectContexts. In most usages such a transaction isn’t needed. Another point with distributed transactions is, that the “Distributed Transaction Service” must be running.

using (var tx = new TransactionScope() 
{
    using (var ctx = new MyObjectContext()) 
    {
        // do your stuff
        ctx.SaveChanges();
    }
    tx.Complete();
}


Discussion