Transaction scope timeout on 10 minutes

我与影子孤独终老i 提交于 2019-11-28 17:53:06

Hello you can verify maxTimeout in your config file, if you don't have this section on your web.config or app.config

Verify your machine.config

<configuration> 
  <system.transactions>
    <machineSettings maxTimeout=""/>
  </system.transactions>
</configuration> 

Adjust the value

To further clarify:

Transaction Scope uses the Machine config setting as the maximum timeout. The default machine timeout is 10 minutes.

Setting the machine config to 2 hours:

      <system.transactions>
        <machineSettings maxTimeout="02:00:00"/>
      </system.transactions> 

The app.config or web.config can be used reduced to the timeout but can not be used to exceed the machine config timeout.

Setting the app config to 1 hour:

<system.transactions>
     <defaultSettings timeout="01:00:00" />
</system.transactions>

Also we did NOT receive any exceptions when the limit was reached, also no trace or event log records.

Also the TransactionScope object has constructor overloads which allow you to specify a timeout, but I'm not sure how that is handled.

Jupaol

To allow transaction to take more than 10 minutes, without need to change machine.config, use this code

    private void SetTransactionManagerField(string fieldName, object value)
    {
        typeof(TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, value);
    }

    public TransactionScope CreateTransactionScope(TimeSpan timeout)
    {
        SetTransactionManagerField("_cachedMaxTimeout", true);
        SetTransactionManagerField("_maximumTimeout", timeout);
        return new TransactionScope(TransactionScopeOption.RequiresNew, timeout);
    }

Usage:

using (var ts = CreateTransactionScope(TimeSpan.FromMinutes(20)))
{ 
    DoLongCode();
    ts.Complete();
}

Based on this article The code of article was originally pasted here. The code in the answer is now refactored and simplified.

They dont' work because is the wrong context where you are trying to change timeout.

try to change it closer to the effective query.

You should have these contexts:

    using (var txn = new TransactionScope(
                            TransactionScopeOption.Required,
                            new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted, Timeout = new TimeSpan(1,0,0) })) // 1 hour or wathever, will not affect anything
                    {

                        using (SqlConnection connection = new SqlConnection(ConnectionString))
                        {
                            int ct = connection.ConnectionTimeout // (read Only, this is the effective default timeout is 15 seconds)
                            connection.Open();

                            SqlCommand select = new SqlCommand(sql.query, connection); // bind to server
                            select.CommandTimeout = 0; // <-- here does apply infinite timeout
SqlDataReader reader = select.ExecuteReader(); // never stop

Considering a full trust environment, you can override max timeout using reflection:

            //Get machineSettings session
            var machineSettings = (System.Transactions.Configuration.MachineSettingsSection)ConfigurationManager.GetSection("system.transactions/machineSettings");
            //Allow modifications
            var bReadOnly = (typeof(ConfigurationElement)).GetField("_bReadOnly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            bReadOnly.SetValue(machineSettings, false);
            //Change max allowed timeout
            machineSettings.MaxTimeout = TimeSpan.MaxValue;

            using (var t = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1,0,0))) { //1 hour transaction
                //...
            }

I resolve this problem modifying the "physical file" machine.config.


1. You have to localize the file:

  • 32 Bits: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machie.config
  • 64 Bits: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

2. You have to add the following code:

<system.transactions>
     <defaultSettings timeout="00:59:00" />
</system.transactions>

You can add this code in your project to extend the transaction time.

// This is used for set the transaction timeout to 40 minutes.
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, TimeSpan.FromSeconds(2400));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!