88 votes

Erreur - La transaction associée à la connexion actuelle est terminée mais n'a pas été éliminée.

J'ai eu des difficultés à utiliser le TransactionScope Pour regrouper plusieurs requêtes de base de données dans une transaction, j'utilise SqlBulkCopy avec une taille de lot de 500. Lorsque j'ai augmenté la taille du lot à 1000, j'ai obtenu l'erreur suivante :

La transaction associée à la connexion actuelle est terminée mais n'a pas été éliminée. La transaction doit être éliminée avant que la connexion puisse être utilisée pour exécuter des instructions SQL.

Voici le code que j'utilise :

using (var scope = new TransactionScope())
{
    using (var connection = (SqlConnection)customerTable.OpenConnection())
    {
        var table1BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName1
        };

        table1BulkCopy.WriteToServer(table1DataTable);

        var table2BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName2
        };

        table2BulkCopy.WriteToServer(table2DataTable);

        var table3BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName3
        };

        table1BulkCopy.WriteToServer(table3DataTable);

        var table4BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName4
        };

        table4BulkCopy.WriteToServer(table4DataTable);

        scope.Complete();
    }
}

158voto

Anthony Queen Points 867

Cela peut se produire lorsque la transaction est interrompue. Vous pouvez augmenter le délai d'attente de votre transaction comme suit (utilisez des valeurs appropriées pour la durée prévue de votre transaction). Le code ci-dessous est pour 15 minutes :

using (TransactionScope scope = 
             new TransactionScope(TransactionScopeOption.Required, 
                                   new System.TimeSpan(0, 15, 0)))
  {
      // working code here
  }

C'est pourquoi il aurait pu fonctionner pour la taille de lot 500 et pas pour 1000.

7 votes

J'obtiens ceci avec Timeout = TransactionManger.MaximumTimeout Ce n'est donc pas la seule façon dont cette erreur peut se produire.

0 votes

Cette réponse a corrigé un problème que j'avais. Comme @Eric J l'a mentionné, ce n'est pas la seule façon dont cette erreur peut se produire, mais si votre transaction se termine, vous obtenez le message ci-dessus, qui n'a aucun rapport avec le problème.

0 votes

@Pradeep c'est la bonne réponse et devrait être marquée comme telle.

27voto

Ads Points 116

J'ai constaté que le réglage du délai d'attente dans le TransactionScope ne fonctionnait pas pour moi. J'ai également dû ajouter la clé de configuration suivante au fichier fin de la machine.config <configuration> pour dépasser le délai maximum par défaut de 10 minutes.

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

Crédit : http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html

1 votes

Notez que vous doit mettre cela à la fin de la section config, sinon vous obtiendrez une erreur de IIS.

0 votes

Si je lis les documents sur MaxTimeout y defaultSettings timeout correctement, un machine.config utilisé sans TransactionOptions donne un timeout de 1 minute (et vous êtes autorisé à augmenter à 10 en utilisant TransactionOptions)

8voto

AVD Points 57984

Déplacements scope.Complete(); en dehors de la connection bloc.

using (var scope = new TransactionScope())
{
  using (var connection = (SqlConnection)customerTable.OpenConnection())
   {
    //
   }
  scope.Complete();
}

0 votes

Ici plus d'infos pourquoi ? C'est une très bonne pratique de placer l'appel comme dernière déclaration dans le bloc using. Plus d'informations sur la méthode

2voto

Vortman Points 11

Problème assez évident avec le délai d'attente, mais vous n'obtenez pas d'effet si vous définissez TransactionOptions.Timeout plus haut. Même si vous définissez TimeSpan.MaxValue, vous n'obtenez pas de bénéfice. Peu importe que la propriété Timeout des TransactionOptions soit définie à une valeur supérieure, TransactionOptions.Timeout ne peut pas dépasser la propriété maxTimeout. Vous devriez mettre en place quelques changements dans machine.config .

Vous devriez rapidement trouver le fichier machine.config %windir% \Microsoft.NET\Framework\ votre version \config\machine.config
Et ajoutez ceci <configuration> étiquette :

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

Ici, vous pouvez définir la propriété maxTimeout à 30 minutes.
Voir ci-dessous pour plus de détails http://thecodesaysitall.blogspot.com/2012/04/long-running-systemtransactions.html

1voto

Alexander Shapkin Points 498

La réponse complète doit être plus complète.

Vous devez spécifier - où sera déterminé le délai maximal de transaction - dans le code .Net, ou dans la configuration du serveur.

<sectionGroup name="system.transactions".... 
    ...allowDefinition="MachineOnly"
</sectionGroup>

Dans ce cas, vous pouvez définir le délai maximum dans le fichier machine.config.

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

Ou peut-être voulez-vous remplacer ce facteur dans l'application. Alors dans le fichier machine.config, vous devez définir l'attribut velue :

...allowDefinition="MachineToApplication"

C'est un bon article : https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X