Délai D'Expiration Des Transactions Par Défaut

J'avais l'habitude de définir des délais D'attente de Transaction en utilisant TransactionOptions.Timeout , mais ont décidé pour faciliter la maintenance d'utiliser l'approche config:

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

Bien sûr, après avoir mis cela, je voulais tester cela fonctionnait, donc réduit le délai d'attente à 5 secondes, puis a couru un test qui a duré plus longtemps que cela - mais la transaction ne semble pas avorter! Si j'ajuste le test pour définir TransactionOptions.Délai d'attente de 5 secondes, le test fonctionne comme prévu

Après Enquêter je pense que le problème semble se rapporter à TransactionOptions.Timeout, même si Je ne l'utilise plus.

J'ai toujours besoin d'utiliser TransactionOptions pour pouvoir définir IsolationLevel, mais je ne définis plus la valeur de Timeout, si je regarde cet objet après l'avoir créé, la valeur de timeout est 00:00:00, ce qui équivaut à l'infini. Cela signifie-t-il que ma valeur définie dans le fichier de configuration est ignorée?

Pour résumer:

  • est-il impossible de mélanger la configuration réglage, et l'utilisation de TransactionOptions
  • Si non, est-il un moyen d'extraire le paramètre de configuration à l'exécution, et utilisez ceci pour définir le Propriété Timeout
  • [Modifier] ou Définissez le niveau d'isolement par défaut sans utiliser TransactionOptions
33
demandé sur MattH 2009-08-28 20:45:18

6 réponses

Vous pouvez mélanger le système.les paramètres de configuration des transactions et l'utilisation de la classe TransactionOption, mais il y a certaines choses dont vous devez être conscient.

Si vous utilisez TransactionOption et spécifiez une valeur Timeout, cette valeur sera utilisé au cours de la système.transactions / defaultTimeout valeur.

Ce qui précède est le nœud du problème dans votre cas, je pense. Vous utilisez le TransactionOption pour spécifier le niveau isolation , et comme effet secondaire, vous obtenez un infinite Timeout value car infinite est la valeur de Timeout par défaut pour TransactionOption si elle n'est pas spécifiée. Bien que, je ne suis pas tout à fait sûr pourquoi cela is...it il serait logique de par défaut au délai D'expiration de la Transaction par défaut.

Vous pouvez implémenter votre propre classe D'aide TransactionOptions qui inclut les valeurs par défaut lues depuis l'application.config (si trouvé) ou par défaut à des valeurs raisonnables pour une classe TransactionOption qui peut être utilisée.

Dans tous les cas, vous pouvez toujours limiter cela en utilisant le système.transaction/machineSettings / maxTimeout valeur. Il s'agit d'un paramètre administratif et ne peut être configuré que via la machine.config. Vous obtiendrez une exception ConfigurationException si vous l'essayez depuis app / web.config.

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

Avec l'ensemblemaxTimeout , quelle que soit la valeur de timeout que vous spécifiez, la valeur maximale sera limitée à la valeur maxTimeout. Le maxTimeout par défaut est 00: 10: 00, ou 10 minutes, de sorte que vous n'auriez jamais un délai d'attente infini sur un transaction.

Vous pouvez également définir explicitement le niveau d'isolement des transactions sur la connexion de base de données que vous utilisez dans la transaction. Quelque chose comme cela?

   var connectionString = "Server=.;Database=master;Trusted_Connection=True;";

            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    var sqlTransaction = conn.BeginTransaction(System.Data.IsolationLevel.Serializable);

                    // do database work
                    //
                    sqlTransaction.Commit();


                }

                // do other work..
                //

                scope.Complete();

            }

Dans vos tests, vous devrez peut-être vous assurer de reconstruire pour que l'application.la configuration est régénérée . Dans mes tests, il est apparu que je devais mettre fin à la *.vshost.processus exe pour qu'il prenne le système.changement de configuration de la transaction-bien que je pense que cela a peut-être été un coup de chance. Juste pour info..

44
répondu Zach Bonham 2013-03-04 15:17:51

Vous pouvez obtenir le délai d'attente par défaut (validé) de la configuration en utilisant TransactionManager.DefaultTimeout.

TransactionOptions est une structure qui encapsule le délai d'attente et le niveau d'isolation. Lors de l'initialisation d'une structure en utilisant le constructeur par défaut, il initialisera toujours les membres de la structure à leurs valeurs par défaut:

TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.Timeout == default(TimeSpan); // TimeSpan.Zero
transactionOptions.IsolationLevel == default(IsolationLevel); // IsolationLevel.Serializable

Si vous souhaitez spécifier un IsolationLevel et utiliser le délai d'attente par défaut:

new TransactionOptions()
{
    IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require
    Timeout = TransactionManager.DefaultTimeout
};
46
répondu Ronald 2010-04-27 20:17:34

Par réflecteur, les règles de base pour définir un délai de transaction avec les constructeurs de TransactionScope sont les suivantes:

Le DefaultTimeOut est déterminé par la première règle d'en bas qui est satisfaite:

  • si le constructeur a un paramètre TimeSpan, DefaultTimeout est le paramètre
  • si le constructeur a un paramètre TransactionOption, le paramètre DefaultTimeout est transactionOption.TimeOut
  • si le constructeur a un paramètre TransactionScopeOption, le paramètre DefaultTimeout est scopeOption.TimeOut
  • si le constructeur n'a pas de paramètre timeout, DefaultTimeout est la valeur spécifiée dans le fichier de configuration de l'application ou du web.
  • sinon, DefaultTimeOut vaut 1 minute.

Le MaxTimeOut est de 10 minutes sauf si une autre valeur est spécifiée dans la machine.config.

Le délai d'attente effectif pour la transaction est plus petit entre MaxTimeOut et DefaultTimeOut qui est supérieur à zéro. Si MaxTimeOut et DefaultTimeOut sont zéro, le délai effectif est le nombre de tiques représentées par long.MaxValue (l'infini).

Si l'instance TransactionScope ne crée pas de nouvelle transaction, soit parce qu'une transaction est passée dans son constructeur, soit parce que l'option transaction scope ne l'exige pas (par exemple, lorsqu'une transaction ambiante est présente et que TransactionScopeOption est requise), mais qu'un paramètre timeOut est toujours passé dans le constructeur, Un minuteur est démarré. Lorsque le délai d'expiration s'écoule, le sous-jacent la méthode TimeOut() de la transaction est appelée. Les propriétés DefaultTimeOut et MaxTimeOut ne sont pas utilisées dans ce cas.

Si le transactionScopeOption == TransactionScopeOption.Supress, le délai d'attente est ignoré et n'a aucun effet.

Il est également possible de définir le MaxTimeOut dans le fichier de configuration app/web, si la section pertinente de la machine.config est remplacé (notez les valeurs des attributs allowDefintion et allowExeDefinition):

<sectionGroup name="system.transactions" type="System.Transactions.Configuration.TransactionsSectionGroup, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null">
    <section name="defaultSettings" type="System.Transactions.Configuration.DefaultSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
    <section name="machineSettings" type="System.Transactions.Configuration.MachineSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" allowDefinition="MachineToApplication" allowExeDefinition="MachineToApplication"/>
</sectionGroup>

Pour une référence rapide, voici le TransactionScope constructeurs:

public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption);
public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption);
public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions);
public TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout);
public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout);
public TransactionScope(TransactionScopeOption scopeOption);
9
répondu Raghu Dodda 2013-01-04 04:52:11

Le paramètre de fichier de configuration est ignoré lorsque TransactionOptions est utilisé. La création D'un TransactionScope créera, dans la plupart des cas, une instance de CommittableTransaction. Le constructeur No arg de CommittableTransaction utilisera le paramètre de fichier de configuration comme délai d'attente par défaut. Les constructeurs TransactionScope qui prennent une TransactionOptions ou TimeSpan appelleront l'une des surcharges de la classe CommittableTransaction et non la version no arg. Donc si vous voulez utiliser cette valeur vous devez la saisir partir du fichier de configuration vous-même.

Quand j'ai rencontré ceci, j'ai mis le code suivant dans une petite classe TransactionOptionsFactory.


Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSectionGroup sectionGroup = configuration.GetSectionGroup("system.transactions");
DefaultSettingsSection defaultSettings = (DefaultSettingsSection) sectionGroup.Sections["defaultSettings"];
TransactionOptions options = new TransactionOptions();
options.Timeout = defaultSettings.Timeout;
options.IsolationLevel = IsolationLevel.ReadCommitted;
6
répondu Mike Two 2009-09-04 21:25:34
void Main()
{
    var maximumTimeout = TransactionManager.MaximumTimeout;//This step is necessary to init _maximumTimeout value, 

    FieldInfo fieldInfo = typeof(TransactionManager).GetFields(BindingFlags.NonPublic | BindingFlags.Static).Single(item => item.Name == "_maximumTimeout");
    var customMaximumTimeout = TimeSpan.FromHours(1);
    fieldInfo.SetValue(null, customMaximumTimeout);
    maximumTimeout = TransactionManager.MaximumTimeout;

    Console.WriteLine(maximumTimeout);//01:00:00
    // use TransactionScope
}
2
répondu Franz 2013-07-26 10:50:59

Pour mettre mes pensées actuelles vers le bas:

  • il est impossible de mélanger le paramètre de configuration et L'utilisation de TransactionOptions
  • la seule façon d'extraire le paramètre de configuration à l'exécution est de lire l'application.config en tant que fichier XML
  • le niveau d'isolement par défaut ne peut être effectué que via les options de transaction, ou au niveau du service dans WCF en utilisant les attributs
1
répondu MattH 2009-09-01 12:06:21