"Cette opération SQL est terminée; elle n'est plus utilisable."... erreur de configuration?
je travaille là-dessus depuis environ un jour et demi maintenant, et j'ai cherché de nombreux blogs et articles d'aide sur le Web. J'ai trouvé plusieurs questions sur SO liées à cette erreur, mais je ne pensais pas qu'elles s'appliquaient tout à fait à ma situation (ou dans certains cas, malheureusement, je ne pouvais pas les comprendre assez bien pour mettre en œuvre :P). Je ne suis pas sûr de pouvoir décrire cela assez bien pour de l'aide... mais va ici:
nous avons une application .NET pour suivre nos ressources. Il y a une fonction d'exportation pour copier ressource du système de suivi du temps et du système de facturation; elle accède à une procédure stockée qui est reliée aux bases de données sur le temps et la facturation.
j'ai récemment déplacé la base de données du système de facturation sur un nouveau serveur (serveur original: Server 2003 SP2, SQL 2005; nouveau serveur: Server 2008 R2, SQL 2008 R2). J'ai un serveur connecté qui pointe vers les bases de données 2008. J'ai mis à jour la procédure stockée pour pointer vers le serveur 2008, et puis j'ai eu une erreur à propos de MSDTC et RPC (http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html). J'ai activé 'rpc / rpc out' sur le serveur lié et défini MSDTC pour permettre L'accès au réseau (quelque chose comme ceci:http://www.sqlwebpedia.com/content/msdtc-troubleshooting).
maintenant je vois ce qui précède, quand j'essaie d'exécuter la fonction export: "cette opération SQL est terminée; elle n'est plus utilisable."Ce qui me semble étrange, c'est que lorsque j'exécute la procédure stockée (à partir du SSMS), elle dit: se termine avec succès.
personne n'A jamais vu cela auparavant? Ai-je manqué quelque chose dans la configuration? Je continue à parcourir les mêmes pages, et la seule chose que j'ai trouvée est que je n'ai pas redémarré après avoir fait les modifications MSDTC (mentionné ici: http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/7172223f-acbe-4472-8cdf-feec80fd2e64/).
je peux poster tout ou partie de la procédure stockée, si cela peut aider... s'il vous plaît laissez-moi savoir.
7 réponses
je crois que ce message d'erreur est dû à une "transaction zombie".
cherchez les endroits où la transaction est commise deux fois (ou refoulée deux fois, ou refoulée et engagée, etc.). Le code .Net engage-t-il la transaction après que le fournisseur de services L'a déjà engagée? Le code .Net le renvoie - t-il en cas d'erreur, puis tente-t-il de le faire à nouveau dans une clause catch (ou finalement)?
il est possible qu'une condition d'erreur n'ait jamais été atteinte sur l'ancien serveur, et donc le code "double rollback" défectueux n'a jamais été touché. Peut-être que maintenant vous avez une situation où il quelques erreurs de configuration sur le nouveau serveur, et maintenant le code défectueux est frappé par la gestion des exceptions.
pouvez-vous déboguer dans le code d'erreur? Vous avez une trace de pile?
j'ai eu cela récemment après avoir refacturé dans un nouveau directeur de connexion. Une nouvelle routine a accepté une transaction pour qu'elle puisse être exécutée en tant que partie d'un lot, le problème était avec un bloc d'utilisation:
public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
using (transaction.Connection)
{
using (transaction)
{
return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}
}
}
il semble que l'utilisation de l'extérieur fermait la connexion sous-jacente ainsi toute tentative de commettre ou de faire reculer la transaction a vomi le message "This SqlTransaction has completed; it is no longer usable."
j'ai enlevé les usings a ajouté un test de couverture et le problème a disparu.
public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}
Vérifier tout ce qui pourrait fermer la connexion dans le contexte d'une transaction.
j'ai récemment rencontré une situation similaire. Pour déboguer dans N'importe quelle version VS IDE, ouvrez les exceptions de Debug (Ctrl + D, E) - cochez toutes les cases contre la colonne "lancer", et lancez l'application en mode de débogage. J'ai réalisé que l'une des tables n'était pas correctement importée dans la nouvelle base de données, donc L'Exception Sql interne tuait la connexion, ce qui entraîne cette erreur.
l'Essentiel de l'histoire est, Si Précédemment code du travail renvoie cette erreur sur une nouvelle base de données, ce pourrait être problème manquant de schéma de base de données, réalisé par le Conseil de débogage ci-dessus,
J'Espère Que Ça Aide, HydTechie
dans mon cas, le problème était que l'une des requêtes incluses dans la transaction soulevait une exception, et même si l'exception a été "gracieusement" traitée, il a quand même réussi à faire reculer toute la transaction.
mon pseudo-code était comme:
var transaction = connection.BeginTransaction();
for(all the lines in a file)
{
try{
InsertLineInTable(); // INSERT statement might fail and throw an exception
}
catch {
// notify the user about the error on line x and continue
}
}
// Commit and Rollback will fail if one of the queries
// in InsertLineInTable threw an exception
if(CheckTableForErrors())
{
transaction.Commit();
}
else
{
transaction.Rollback();
}
j'ai le même problème. Cette erreur se produit parce que la mise en commun de la conection. Lorsqu'il existe deux ou plusieurs utilisateurs ont accès au système, la connexion Mise en commun réutilise une connexion et la transaction également. Si le premier utilisateur exécute commit ou rollback, la transaction n'est plus utilisable.
vérifiez également les processus en cours d'exécution à partir de votre application .NET par rapport à la base de données. Par exemple, vous pouvez appeler une procédure stockée ou une requête qui n'ont pas assez de temps pour terminer ce qui peut montrer, dans vos journaux:
Le Délai D'Exécution A Expiré. Le délai écoulé avant la fin de l'opération ou le serveur ne répond pas.
- cette opération SQL est terminée; elle n'est plus utilisable.
Vérifiez la commande timeout settings Essayez d'exécuter une trace (profiler) et voir ce qui se passe du côté de la base de données...
voici un moyen de détecter la transaction Zombie
SqlTransaction trans = connection.BeginTransaction();
//some db calls here
if (trans.Connection != null) //Detecting zombie transaction
{
trans.Commit();
}
décompressant la classe SqlTransaction, vous verrez ce qui suit
public SqlConnection Connection
{
get
{
if (this.IsZombied)
return (SqlConnection) null;
return this._connection;
}
}
je remarque que si la connexion est fermée, le transOP va devenir zombie, donc ne peut pas Commit
.
Pour mon cas, c'est parce que j'ai l' Commit()
dans un finally
bloc, tandis que la connexion a été dans le try
bloc. Cette disposition entraîne l'élimination de la connexion et la collecte des ordures. La solution était de mettreCommit
à l'intérieur de l' try
bloquez à la place.