J'ai une application qui effectue potentiellement des milliers d'insertions dans une base de données SQL Server 2005. Si une insertion échoue pour une raison quelconque (contrainte de clé étrangère, longueur de champ, etc.), l'application est conçue pour enregistrer l'erreur d'insertion et continuer.
Chaque insertion étant indépendante des autres, les transactions ne sont pas nécessaires pour l'intégrité de la base de données. Cependant, nous souhaitons les utiliser pour le gain de performance. Lorsque j'utilise les transactions, nous obtenons l'erreur suivante sur environ un commit sur cent.
This SqlTransaction has completed; it is no longer usable.
at System.Data.SqlClient.SqlTransaction.ZombieCheck()
at System.Data.SqlClient.SqlTransaction.Commit()
Pour essayer de trouver la cause, j'ai placé des instructions de suivi à chaque opération de transaction afin de m'assurer que la transaction n'était pas fermée avant d'appeler le commit. J'ai confirmé que mon application ne fermait pas la transaction. J'ai ensuite relancé l'application en utilisant exactement les mêmes données d'entrée et elle a réussi.
Si j'éteins la connexion, l'échec persiste. Si je l'active à nouveau, il réussit. Cette activation/désactivation s'effectue via le fichier app.config sans qu'il soit nécessaire de recompiler.
Il est évident que l'acte d'enregistrement modifie le timing et le fait fonctionner. Cela indiquerait un problème de threading. Cependant, mon application n'est pas multithreadée.
J'ai vu une entrée dans la base de données MS indiquant qu'un bogue dans le cadre de .Net 2.0 pouvait causer des problèmes similaires ( http://support.microsoft.com/kb/912732 ). Cependant, la solution qu'ils ont fournie ne résout pas ce problème.