我一直在使用TransactionScope
将多个数据库查询包装到事务中时遇到问题,我正在使用带有batchsize 500的SqlBulkCopy。当我将批量大小增加到1000时,我收到错误:< / p>
与当前连接关联的事务已完成 但尚未处理。交易必须在交易之前处理 连接可用于执行SQL语句。
这是我正在使用的代码:
using (var scope = new TransactionScope())
{
using (var connection = (SqlConnection)customerTable.OpenConnection())
{
var table1BulkCopy = new SqlBulkCopy(connection)
{
BatchSize = BATCH_SIZE,
DestinationTableName = TableName1
};
table1BulkCopy.WriteToServer(table1DataTable);
var table2BulkCopy = new SqlBulkCopy(connection)
{
BatchSize = BATCH_SIZE,
DestinationTableName = TableName2
};
table2BulkCopy.WriteToServer(table2DataTable);
var table3BulkCopy = new SqlBulkCopy(connection)
{
BatchSize = BATCH_SIZE,
DestinationTableName = TableName3
};
table1BulkCopy.WriteToServer(table3DataTable);
var table4BulkCopy = new SqlBulkCopy(connection)
{
BatchSize = BATCH_SIZE,
DestinationTableName = TableName4
};
table4BulkCopy.WriteToServer(table4DataTable);
scope.Complete();
}
}
答案 0 :(得分:107)
当交易超时时会发生这种情况。您可以像这样增加事务的超时(使用适合预期事务长度的值)。以下代码为15分钟:
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.Required,
new System.TimeSpan(0, 15, 0)))
{
// working code here
}
这就是为什么它可以用于batchsize 500而不是1000.
答案 1 :(得分:19)
我发现在TransactionScope中设置超时对我不起作用。我还需要将以下配置密钥添加到machine.config <configuration>
标记的末尾,以延长超过10分钟的默认最大超时时间。
<system.transactions>
<machineSettings maxTimeout="00:30:00" /> <!-- 30 minutes -->
</system.transactions>
信用: http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html
答案 2 :(得分:7)
将scope.Complete();
移到connection
区块之外。
using (var scope = new TransactionScope())
{
using (var connection = (SqlConnection)customerTable.OpenConnection())
{
//
}
scope.Complete();
}
答案 3 :(得分:0)
完整答案必须更加完整。
您必须在.Net代码或服务器配置中指定 - 确定最大事务超时的位置
<sectionGroup name="system.transactions"....
...allowDefinition="MachineOnly"
</sectionGroup>
在这种情况下,您可以在machine.config
中设置max timeout<configuration>
<system.transactions>
<machineSettings maxTimeout="01:00:00" />
</system.transactions>
</configuration>
或者您可能希望在应用程序中覆盖此行为。然后 在machine.config中你应该设置属性:
...allowDefinition="MachineToApplication"
这是一个很好的arcticle:https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/
答案 4 :(得分:0)
超时的问题很明显,但是如果将TransactionOptions.Timeout设置得较高,则不会生效。 即使您设置TimeSpan.MaxValue,您实际上也不会获得利润。不必将TransactionOptions的Timeout属性设置为更高的值,TransactionOptions.Timeout不能超过maxTimeout属性。 您应该在 machine.config 中进行一些更改。
不久,您应该找到machine.config文件
%windir%\ Microsoft.NET \ Framework \ 您的版本 \ config \ machine.config
并将其添加到<configuration>
标签中:
<system.transactions>
<machineSettings maxTimeout="00:30:00"/>
</system.transactions>
您可以在此处将maxTimeout属性设置为30分钟。
有关更多详细信息,请参见以下内容http://thecodesaysitall.blogspot.com/2012/04/long-running-systemtransactions.html
答案 5 :(得分:0)
C#9 Lang版本。 TransactionScopeOption.Suppress对我来说就像魔术一样。
// TransactionScopeOption.Suppress works and fixed my issue
using TransactionScope Scope = new TransactionScope(TransactionScopeOption.Suppress);
try
{
using var CentralConnection = SQLConnection("Other connection string here");
using var LocalConnection = SQLConnection("Other connection string here");
// Central
using var cmd0 = new SqlCommand("OtherSQLCommandTextHere", CentralConnection)
{
CommandTimeout = 0 // I just add zero timeout here
};
cmd0.ExecuteNonQuery();
// Local
using var cmd1 = new SqlCommand("OtherSQLCommandTextHere", LocalConnection)
{
CommandTimeout = 0 // I just add zero timeout here
};
cmd1.ExecuteNonQuery();
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
Scope.Complete();
}
catch (Exception ex)
{
Scope.Dispose();
MessageBox.Show(ex.ToString());
}
public SqlConnection SQLConnection(string ISQLConnection)
{
SqlConnection conn = null;
try
{
conn = new SqlConnection(ISQLConnection);
conn.Open();
}
catch
{
// skipping here error message
}
return conn;
}