我有一个例程,它使用递归循环将项插入SQL Server 2005数据库。启动循环的第一个调用包含在使用TransactionScope的事务中。当我第一次调用ProcessItem时,myItem数据会按预期插入到数据库中。但是,当从ProcessItemLinks或ProcessItemComments调用ProcessItem时,我收到以下错误。
“该操作对交易状态无效”
我在Windows 7的VS 2008调试中运行它,并运行MSDTC以启用分布式事务。下面的代码不是我的生产代码,但设置完全相同。 AddItemToDatabase是我无法修改的类上的方法,它使用标准的ExecuteNonQuery()创建连接,然后关闭并在完成后进行处置。
我已经查看过此处和互联网上的其他帖子,仍然无法解决此问题。任何帮助将不胜感激。
using (TransactionScope processItem = new TransactionScope())
{
foreach (Item myItem in itemsList)
{
ProcessItem(myItem);
}
processItem.Complete();
}
private void ProcessItem(Item myItem)
{
AddItemToDatabase(myItem);
ProcessItemLinks(myItem);
ProcessItemComments(myItem);
}
private void ProcessItemLinks(Item myItem)
{
foreach (Item link in myItem.Links)
{
ProcessItem(link);
}
}
private void ProcessItemComments(Item myItem)
{
foreach (Item comment in myItem.Comments)
{
ProcessItem(comment);
}
}
这是堆栈跟踪的顶部。不幸的是,我无法将此处的构建显示为公司敏感信息,我无法透露。
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()
答案 0 :(得分:24)
分布式交易使我的头发过早变灰了:)
常见嫌疑人
使用dtcping等工具测试MSDTC是否正常工作
首先插入少量元素进行测试。您的代码似乎处于递归循环中,可以处理大量数据。也许您正在运行许多查询,并且事务已超时。
有时System.Transactions.Transaction.Current对发生的事情有一些线索。针对此全局变量添加监视
答案 1 :(得分:2)
默认最大超时为10分钟。您可以在machine.config中覆盖它:
<configuration>
<system.transactions>
<machineSettings maxTimeout="00:00:30" />
</system.transactions>
</configuration>
或者您可以使用反射在代码中覆盖它:
private static void OverrideTransactionScopeMaximumTimeout(TimeSpan timeOut)
{
// 1. create a object of the type specified by the fully qualified name
Type oSystemType = typeof(global::System.Transactions.TransactionManager);
System.Reflection.FieldInfo oCachedMaxTimeout = oSystemType.GetField("_cachedMaxTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
System.Reflection.FieldInfo oMaximumTimeout = oSystemType.GetField("_maximumTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
oCachedMaxTimeout.SetValue(null, true);
oMaximumTimeout.SetValue(null, timeOut);
// For testing to confirm value was changed
// MessageBox.Show(string.Format("DEBUG SUCCESS!! Maximum Timeout for transactions is '{0}'", TransactionManager.MaximumTimeout.ToString()));
}