Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction scope timeout on 10 minutes

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)
    {
        // or for netcore / .net5+ use these names instead:
        //    s_cachedMaxTimeout
        //    s_maximumTimeout
        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.


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.


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


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