use*_*862 15 c# sql stored-procedures app-config transactionscope
我在这段代码中使用TransactionScope:
private void ExecuteSP()
{
bool IsComplete = false;
SqlCommand sqlComm = null;
//6 hours!!!
TimeSpan ts1 = new TimeSpan(6, 0, 0);
try
{
using (TransactionScope t = new TransactionScope(TransactionScopeOption.RequiresNew, ts1))
{
using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
{
//open sql connection
sqlConn.Open();
try
{
//create new sqlCommand
sqlComm = new SqlCommand();
for (int i = 1; i <= 2; i++)
{
IsComplete = true;
//This command takes 15 minutes
sqlComm.CommandText = "exec TestSp";
sqlComm.Connection = sqlConn;
sqlComm.CommandType = CommandType.Text;
sqlComm.CommandTimeout = 18000;
//Executing my command
int j = sqlComm.ExecuteNonQuery();
}
//End
t.Complete();
}
catch (Exception ex)
{
IsComplete = false;
string Message = ex.Message;
}
finally
{
if (sqlComm != null)
sqlComm.Dispose();
}
}
}
}
catch (Exception ex)
{
string messagee = ex.Message;
//do something
}
finally
{
MessageBox.Show("Finsh");
}
}
Run Code Online (Sandbox Code Playgroud)
这是在一次执行(sqlCommand.ExecuteNonQuery();)之后发生的,执行时间超过10分钟.在这一点上我没有得到任何激励,在下一个例外中,我得到了这个例外:
The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.
Run Code Online (Sandbox Code Playgroud)
这是因为System.Transactions.TransactionManager.MaximumTimeout设置为10分钟的TimeSpan.
我搜索并发现它可能与"System.Transactions - > machine.config的maxTimeout"有关但在将配置更改为此文件后出现异常:
<?xml version="1.0"?>
<configuration>
<system.transactions>
<machineSettings maxTimeout="10:00:00"/>
</system.transactions>
<appSettings>
<add key="FileName" value="MyFileName" />
<add key="MySpace" value="5 MB" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
</configuration>
Run Code Online (Sandbox Code Playgroud)
当我在更改配置文件后尝试在运行时获取System.Transactions.TransactionManager.MaximumTimeout时,我得到此异常:
"配置系统无法初始化"
有没有人知道如何解决这个问题?
(关于我的情况的一般说明:我需要做大约20分钟的存储过程,因为我需要将包含int的表转换为SQL中的bigint(int = 32bit,bigint = 64位).我需要创建新表并插入使用int64从旧表到新表的数据.通过ID连接到其他4个表的表,每个表包含超过2000万行,还有绑定,索引等等.我不能将此过程拆分为小存储过程所以我需要将最大超时更改为一小时或更长时间,10分钟是不够的!).
Mat*_*utt 30
如果您不害怕使用反射,您实际上可以通过编程方式覆盖最大超时.此代码不保证是面向未来的,但它适用于.NET 4.0.
public static class TransactionmanagerHelper
{
public static void OverrideMaximumTimeout(TimeSpan timeout)
{
//TransactionScope inherits a *maximum* timeout from Machine.config. There's no way to override it from
//code unless you use reflection. Hence this code!
//TransactionManager._cachedMaxTimeout
var type = typeof(TransactionManager);
var cachedMaxTimeout = type.GetField("_cachedMaxTimeout", BindingFlags.NonPublic | BindingFlags.Static);
cachedMaxTimeout.SetValue(null, true);
//TransactionManager._maximumTimeout
var maximumTimeout = type.GetField("_maximumTimeout", BindingFlags.NonPublic | BindingFlags.Static);
maximumTimeout.SetValue(null, timeout);
}
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
TransactionmanagerHelper.OverrideMaximumTimeout(TimeSpan.FromMinutes(30));
Run Code Online (Sandbox Code Playgroud)
Chr*_*n.K 12
你不能指定machineSettings在自己的配置文件,但实际上你需要更改/添加machineSettings\maxTimeout了在machine.config计算机的文件.
在您的计算机上,每个32/64位和CLR版本组合都有一个此文件实例.例如,.NET 2.0的32位版本文件位于%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG目录中.64位.NET 2.0应用程序的文件位于%windir%\Microsoft.NET\Framework64\v2.0.50727\CONFIG目录中.同样,如果您使用的是.NET 4.0,则需要更改v4.0.30319\Config子目录中的文件.
请注意,通过更改此文件(名称应该暗示),您可以更改框中每个事务的最大超时.所以要小心你在这里设置的内容.在您的示例中,您将超时更改为10(!)小时.
过长的事务超时可能是一个问题,因为有时在达到超时之前无法检测到死锁.因此,有时无法及时发现这种情况.还有其他原因可以避免长时间运行的事务,但这实际上超出了这个问题/答案的范围.
无论如何,单个应用程序仍然可以设置自己的最大超时,但是总是machine.config使用system.transactions自己的配置文件中的部分来限制文件中的超时:
<system.transactions>
<defaultSettings timeout="22:00:00"/>
</system.transactions>
Run Code Online (Sandbox Code Playgroud)
请注意,此处的元素名称defaultSettings不是machineSettings.
您还可以查看以下链接以获取更多信息:
我从您的代码中注意到的一件事与 MS 提供的示例不同,那就是您在完成 SQL 工作之前完成了事务。
例如,
t.Complete();
Run Code Online (Sandbox Code Playgroud)
出现在之前
if (sqlComm != null)
sqlComm.Dispose();
Run Code Online (Sandbox Code Playgroud)
你的 t.complete(); 确实需要移至 sql 段的末尾。我还没有运行它来证明它有效,但它是有意义的,因为你有一个事务部分,然后在你告诉它完成后可以进行进一步的工作。
我以此作为参考:http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
| 归档时间: |
|
| 查看次数: |
25770 次 |
| 最近记录: |