我有几种看起来像这样的代码方法:

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();
        }
    }
}

我现在需要在外部事务中一起调用这些方法中的几种,所以我做到了:
using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    method1();
    method2();
    method3();
}

但它在做:
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, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()

我需要用IDbTransactions替换TransactionScopes吗?

我应该为外部内部范围使用什么TransactionScopeOption?我猜我想要外部的RequiresNew和内部的Required吗?

这些方法仍将单独调用(即,没有外部TransactionScope以及一起调用,因此我仍然需要它们在事务上是安全的。

谢谢

最佳答案

我相信您在这里混合使用各种技术,应该避免同时使用TransactionScopeDbTransaction,因为TransactionScope创建了隐式事务。

因此,我建议您使用与以下方法类似的方法:

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();
    }
}

然后,您可以一起调用它们:
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    method1();
    method2();
    method3();

    scope.Complete();
}

并且您调用的方法将共享同一笔交易。

关于c# - 如何将IDbTransactions包装在TransactionScope中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6277335/

10-12 01:37