web-dev-qa-db-fra.com

Délai d'expiration de la portée de la transaction après 10 minutes

J'ai une longue course TransactionScope en C #. J'ai dit au champ d'application qu'il devrait durer longtemps, mais j'ai toujours un délai. Qu'est-ce qui pourrait causer ça?

TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
transactionOptions.Timeout = TimeSpan.MaxValue;
using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{ 
    DoLongCode();
}
24
Patrick

Bonjour, vous pouvez vérifier maxTimeout dans votre fichier de configuration si cette section ne figure pas dans votre web.config ou app.config

Vérifiez votre machine.config

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

Ajuster la valeur

18
Aghilas Yakoub

Pour clarifier davantage:

L'étendue de la transaction utilise le paramètre de configuration de la machine comme délai d'expiration maximal . Le délai d'inactivité par défaut de la machine est de 10 minutes. 

Réglage de la configuration de la machine sur 2 heures: 

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

App.config ou web.config peuvent être utilisés réduits au délai d'attente, mais ne peuvent pas être utilisés pour dépasser le délai d'attente de configuration de la machine. 

Réglage de la configuration de l'application sur 1 heure:

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

De plus, nous n'avons reçu AUCUNE exception lorsque la limite a été atteinte, et aucun enregistrement de trace ou de journal des événements. 

De plus, l'objet TransactionScope a des surcharges de constructeur qui vous permettent de spécifier un délai d'expiration, mais je ne sais pas comment cela est géré.

30
Eric Schneider

Pour permettre aux transactions de prendre plus de 10 minutes, sans avoir besoin de changer de machine.config, utilisez ce 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();
}

Basé sur cet articleLe code de l'article a été collé à l'origine ici. Le code de la réponse est maintenant refactoré et simplifié.

23
Jupaol

Ils ne fonctionnent pas parce que c'est le mauvais contexte dans lequel vous essayez de changer le délai d'attente.

essayez de le changer plus près de la requête effective.

Vous devriez avoir ces contextes:

    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
4
Fabio Guerrazzi

En considérant un environnement de confiance complet, vous pouvez remplacer le délai d'expiration maximal à l'aide de la réflexion:

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

Je résous ce problème en modifiant le "fichier physique" machine.config .


1. Vous devez localiser le fichier:

  • 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. Vous devez ajouter le code suivant:

<system.transactions>
     <defaultSettings timeout="00:59:00" />
</system.transactions>
1
Victor Campos Lins

Vous pouvez ajouter ce code dans votre projet pour prolonger le temps de transaction.

// 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));
0
Mantu