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
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 valeurTimeout
, 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..
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
};
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 esttransactionOption.TimeOut
- si le constructeur a un paramètre
TransactionScopeOption
, le paramètre DefaultTimeout estscopeOption.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);
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;
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
}
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