Transaction scope timeout on 10 minutes

74,157

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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
                //...
            }

Solution 5

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>
Share:
74,157
Patrick
Author by

Patrick

Updated on November 18, 2021

Comments

  • Patrick
    Patrick over 2 years

    I have a long running TransactionScope in C#. I told the scope that it should have a long timespan, but still I get a timeout. What could cause this?

    TransactionOptions transactionOptions = new TransactionOptions();
    transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
    transactionOptions.Timeout = TimeSpan.MaxValue;
    using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
    { 
        DoLongCode();
    }
    
  • schglurps
    schglurps over 11 years
    In Windows Azure this cannot be changed, 10 minutes is the maximum timeout.
  • Aghilas Yakoub
    Aghilas Yakoub over 11 years
    Yes it's possible to override machine.config
  • jpierson
    jpierson over 11 years
    According to this thread on MSDN you cannot override the maxTimeout value in your web.config or app.config file. social.msdn.microsoft.com/Forums/da-DK/…
  • springy76
    springy76 almost 10 years
    @jpierson I really hate Microsoft for this. Why should I change a system setting when there is just this single app which needs extraordinary behavior. Have they ever thought about exclusive mode local DBs like 'LocalDB', 'SQLCe', 'SQLite'? NO!
  • Maxim
    Maxim over 6 years
    Possible limitation: it should be called before any transaction (works fine in console, but not in web app).
  • martinoss
    martinoss over 4 years
    Not how I wished to implement it, but It's a solution and works for me (Azure WebJob)
  • Josh
    Josh over 4 years
    I like this solution a lot as in many environments you have no access to the machine.config and this solution does work as intended.
  • Alan Fluka
    Alan Fluka almost 4 years
    For me, the fields were named s_cachedMaxTimeout and s_maximumTimeout, so I've changed it to try either field name and use what works. This is still pretty much a hack (as noted in the original article), but sometimes there really is no other option.
  • Gert Arnold
    Gert Arnold over 3 years
    Please... reflection should never be used to set inaccessible members because, basically, you don't know what you're doing. There are legal method to do what OP wants. Also, this is a repetition of an existing answer.
  • Gert Arnold
    Gert Arnold over 3 years
    Which perfectly demonstrates the problem with this hack. It breaks easily. This should never be used in production code. Who knows, in a next version these members may be completely gone and you have a big problem.
  • David Liebeherr
    David Liebeherr almost 3 years
    @GertArnold I would generally agree that setting the value of a private member of a type that you do not own is a very bad idea. However I do not agree for this specific scenario. AFAIK the only officially supported way to increase the maximum for the transaction timeout is modifying the machine.config. However this is something we are all to often not allowed to do, because of the IT policies that are in place. Almost none of my customers would allow anyone to make such a change. Therefore using the mentioned hack is AFAIK the only possible alternative solution to this problem.
  • Gert Arnold
    Gert Arnold almost 2 years
    Even then, it only repeats this answer.