开发者

How to wrap IDbTransactions in a TransactionScope

开发者 https://www.devze.com 2023-03-11 00:58 出处:网络
I have several code methods that look like this: using (var connection = this.connectionFactory.GetConnection())

I have several code methods that look like this:

using (var connection = this.connectionFactory.GetConnection())
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        using (var command = connection.CreateCommand())
        {
            command.Transaction = transaction;
            command.CommandText = "foo";
            command.ExecuteNonQuery();
            transaction.Commit();
        }
    }
}

I now need to call several of these methods together inside an outer transaction, So I did this:

using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    method1();
    method2();
    method3();
}

but its doing:

The operation is not valid for the state of the transaction.
   at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction)
   at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, D开发者_高级运维bConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()

Do I need to replace the IDbTransactions with TransactionScopes?

What TransactionScopeOption should I use for the outer an inner scopes? Im guessing i want RequiresNew for the outer and Required for the inners?

The methods will still be called individually (i.e. without an outer TransactionScope as well as together, so I still need them to be transactionally safe.

Thanks


I believe you are mixing technologies here and should avoid using TransactionScope and DbTransaction together because TransactionScope creates an implicit transaction.

So I would recommend to have your methods similar to:

using (var connection = this.connectionFactory.GetConnection())
{
    connection.Open();
    using (TransactionScope scope = new TransactionScope())
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = "foo";
            command.ExecuteNonQuery();
        }
        scope.Complete();
    }
}

Then you can call them together:

using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    method1();
    method2();
    method3();

    scope.Complete();
}

and the methods you called will share the same transaction.


I am not sure of what I will say, but after reading this: http://msdn.microsoft.com/en-us/library/ms172152(v=vs.80).aspx#sectionSection3

I think you should use TransactionScope in your sub method, but we the option Required. So when they are called individually, you still have a transaction, and when you call them in the upper method, the transaction sill be integrated in the ambient transaction.


I guess you are doing it right. The inner transaction is enrolled in the same scope of the outer one, and the whole thing will rollback. To have a new transactionscope you have specify "requiresnew".(which u have mentioned) for more clarity refer this post. http://web.archive.org/web/20091012162649/http://www.pluralsight.com/community/blogs/jimjohn/archive/2005/06/18/11451.aspx

0

精彩评论

暂无评论...
验证码 换一张
取 消