首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TransactionScope maximumTimeout

TransactionScope maximumTimeout
EN

Stack Overflow用户
提问于 2011-06-19 11:12:05
回答 6查看 27.8K关注 0票数 17

我在这段代码中使用TransactionScope:

代码语言:javascript
复制
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");
    }
}

在执行一次(sqlCommand.ExecuteNonQuery();)之后,执行时间超过10分钟就会发生。在这一点上我没有得到任何的解释,在下一次,我得到了一个例外:

代码语言:javascript
复制
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.

这是因为System.Transactions.TransactionManager.MaximumTimeout设置为10分钟的TimeSpan。

我搜索并发现它可能与“System.Transaction->Machine.config的maxTimeout”有关,但在将配置更改为该文件后,我得到了一个异常:

代码语言:javascript
复制
<?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>

在更改配置文件后,当我试图在运行时获得System.Transactions.TransactionManager.MaximumTimeout时,会得到以下异常:

“配置系统初始化失败”

,有人知道如何解决这个问题吗?

(请注意我的情况:我需要执行大约20分钟的存储过程,因为我需要在SQL中将包含int的表转换为bigint (int =32位,bigint =64位)。我需要创建新表,并使用int64将数据从旧表插入到新表中。通过ID连接到其他4个表的表,每个表包含超过2000万行,还有绑定、索引等。我无法将此过程拆分为小型存储过程,因此需要将最大超时更改为一小时或更长时间,10分钟是不够的!)。

EN

回答 6

Stack Overflow用户

发布于 2012-07-03 15:38:37

如果您不害怕使用反射,则实际上可以以编程方式覆盖最大超时。这段代码不一定是未来的证明,但它在.NET 4.0中起作用。

代码语言:javascript
复制
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);
    }
}

你可以这样使用它:

代码语言:javascript
复制
            TransactionmanagerHelper.OverrideMaximumTimeout(TimeSpan.FromMinutes(30));
票数 32
EN

Stack Overflow用户

发布于 2011-06-19 14:07:30

您不能在您自己的配置文件中指定machineSettings,但是您需要在计算机的machine.config文件中实际更改/添加machineSettings\maxTimeout

在您的计算机上,每32/64位和CLR版本组合就有一个此文件的实例。例如,32位版本的.NET 2.0文件位于%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 (!)几个小时。

事务超时时间过长可能是一个问题,因为有时在到达超时之前无法检测到死锁。因此,有时无法及时发现这种情况。应该避免长时间运行的事务还有其他原因,但这实际上超出了这个问题/答案的范围。

无论如何,单独的应用程序仍然可以设置自己的最大超时,但是,使用自己的配置文件中的system.transactions部分,总是会被system.transactions文件中的超时设置为上限:

代码语言:javascript
复制
  <system.transactions>
    <defaultSettings timeout="22:00:00"/>
  </system.transactions>

注意,这里的元素名是defaultSettings,而不是machineSettings

您还可以查看以下链接以获得更多信息:

票数 12
EN

Stack Overflow用户

发布于 2011-06-19 11:19:19

我从您的代码中注意到了一件与MS提供的示例不同的事情,那就是在完成SQL工作之前完成事务。

例如,

代码语言:javascript
复制
 t.Complete(); 

先于

代码语言:javascript
复制
            if (sqlComm != null)
                sqlComm.Dispose();  

您的t.complete();确实需要向下移动到sql段的末尾。我没有运行它来证明它的工作,但它是有意义的,因为您有一个事务部分,然后有进一步的工作,然后你告诉它已经完成。

我使用这个作为参考:http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6402031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档