我有几个代码方法,如下所示:
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
以及一起调用,所以我仍然需要它们在事务上是安全的。
由于
答案 0 :(得分:6)
我相信您在这里混合使用技术,应避免同时使用TransactionScope
和DbTransaction
,因为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();
}
您调用的方法将共享同一个事务。
答案 1 :(得分:0)
我猜你做得对。 内部事务注册在外部事务的相同范围内,整个事务将回滚。 要有一个新的transactioncope,你已经指定了“requiresnew”。(你已经提到了) 为了更清晰,请参阅这篇文章。 http://web.archive.org/web/20091012162649/http://www.pluralsight.com/community/blogs/jimjohn/archive/2005/06/18/11451.aspx
答案 2 :(得分:0)
我不确定我会说什么,但在阅读之后:http://msdn.microsoft.com/en-us/library/ms172152(v=vs.80).aspx#sectionSection3
我认为您应该在子方法中使用TransactionScope
,但我们选择Required
。因此,当它们被单独调用时,您仍然有一个事务,当您使用upper方法调用它们时,事务将被集成到环境事务中。