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();
}
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
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é.
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é.
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
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:
2. Vous devez ajouter le code suivant:
<system.transactions>
<defaultSettings timeout="00:59:00" />
</system.transactions>
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));