Question

Je travaille sur cette question depuis environ un jour et demi, et cherchai blogs numberous et des articles d'aide sur le Web. J'ai trouvé plusieurs questions sur SO liées à cette erreur, mais je ne pensais pas qu'ils tout à fait appliquer à 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 que je peux décrire ce assez bien pour l'aide ... mais va ici:

Nous avons une application .NET pour suivre nos ressources. Il y a une fonction d'exportation pour copier une ressource au système de suivi du temps et le système de facturation; ce accède à une procédure stockée que les liens vers les temps et les bases de données de facturation.

J'ai récemment déplacé la base de données du système de facturation à un nouveau serveur (serveur d'origine: Server 2003 SP2, SQL 2005, nouveau serveur: Server 2008 R2, SQL Server 2008 R2). J'ai un ensemble de serveur lié en pointant vers les bases de données 2008. Je mis à jour la procédure stockée pour pointer vers le serveur 2008, et je suis une erreur sur MSDTC et RPC (http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html). J'activé la fonction « rpc / Rpc out » sur le serveur lié et mis en MSDTC pour permettre l'accès réseau (quelque chose comme ceci: http: // www.sqlwebpedia.com/content/msdtc-troubleshooting ).

Maintenant, je suis en train de ce qui précède, lorsque je tente de lancer la fonction d'exportation: « Ce SqlTransaction a terminé, il ne peut plus être utilisée. » Ce qui semble étrange pour moi est que quand je viens de lancer la procédure stockée (de SSMS), il dit qu'il se termine avec succès.

Quelqu'un at-il vu cela auparavant? Ai-je manqué quelque chose dans la configuration? Je continue sur les mêmes pages, et la seule chose que j'ai trouvé que je ne l'ai pas redémarrer après avoir fait le MSDTC change (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.

Était-ce utile?

La solution

Je crois que ce message d'erreur est due à une "transaction zombie".

Rechercher des domaines où l'transacton est commis deux fois (ou annulée deux fois, ou rétrogradés et engagés, etc.). Est-ce que le code .Net engage la transaction après la SP a déjà commis? Est-ce que le rouleau de code .Net revenir en rencontrant une erreur, puis essayez de rouler à nouveau dans une prise (ou enfin) l'article?

Il est possible une condition d'erreur n'a jamais été fait d'être frappé sur l'ancien serveur, et donc le défaut code « double rollback » n'a jamais été touché. Peut-être que maintenant vous avez une situation où il une erreur de configuration sur le nouveau serveur, et maintenant le code défectueux est d'être frappé par la gestion des exceptions.

Pouvez-vous déboguer dans le code d'erreur? Avez-vous une trace de la pile?

Autres conseils

J'ai eu ce récemment après refactoring dans un nouveau gestionnaire de connexion. Une nouvelle routine a accepté une transaction afin qu'il puisse être exécuté dans le cadre d'un lot, problème était avec un bloc en utilisant:

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'extérieur à l'aide a été la fermeture de la connexion sous-jacente ainsi toute tentative de commettre ou annuler la transaction ont lancé le message "This SqlTransaction has completed; it is no longer usable."

J'ai enlevé les usings 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 être fermer la connexion tout à l'intérieur du contexte d'une transaction.

J'ai le même problème. Cette erreur se produit parce que la mise en commun de conection. Quand existe deux utilisateurs acess le système ou plus, le connetion mise en commun de réutilisation et un connetion la transation aussi. Si le premier utilisateur d'exécuter commit OU annuler la transaction est pas utilisable longe.

J'ai récemment couru à travers la même situation. Pour le débogage dans une version VS IDE, des exceptions ouvertes de débogage (Ctrl + D, E) - vérifier toutes les cases contre la colonne « Jeté », et exécuter l'application en mode débogage. Je me suis rendu compte que l'une des tables n'a pas été importé correctement dans la nouvelle base de données, exception Sql interne a été en train de tuer la connexion, les résultats ainsi dans cette erreur.

Contenu essentiel de l'histoire, si code retourne travail Auparavant, cette erreur sur une nouvelle base de données, cela pourrait être le schéma de base de données d'émission manquantes, par-dessus la pointe realize débogage,

it helps, HydTechie

Dans mon cas, le problème est que l'une des requêtes incluses dans la transaction soulevait une exception, et même si l'exception était « gracieusement » gérée, il a toujours réussi à faire reculer l'ensemble de 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();
}

Vérifiez également tous les processus en cours d'exécution à long exécutés à partir de votre application .NET contre la DB. Par exemple, vous pouvez appeler une procédure ou requête stockée qui n'a pas assez de temps à la fin qui peut montrer dans vos journaux comme:

  • L'exécution Délai d'attente expiré. Le délai écoulé avant achèvement de l'opération ou le serveur ne répond pas.

    • Ce SqlTransaction a terminé; il ne peut plus être utilisée.

Vérifiez les paramètres de délai d'attente de commande Essayez d'exécuter une trace (profileur) et de voir ce qui se passe du côté DB ...

Dans mon cas, j'ai des codes après avoir commis la transaction dans le même bloc catch try. une erreur peut conduit à l'exécution de bloc de capture, qui contient l'annulation de la transaction. Il affiche l'erreur similaire. Par exemple regarder la structure du code ci-dessous:

SqlTransaction trans = null;

try{
 trans = Con.BeginTransaction();
// your codes

  trans.Commit();
//your codes having errors

}
catch(Exception ex)
{
     trans.Rollback(); //transaction roll back
    // error message
}

finally
{ 
    // connection close
}

Hope il aider quelqu'un:)

Here is a way to detect Zombie transaction

SqlTransaction trans = connection.BeginTransaction();

//some db calls here

if (trans.Connection != null) //Detecting zombie transaction
{
  trans.Commit();
}

Decompiling the SqlTransaction class, you will see the following

public SqlConnection Connection
{
  get
  {
    if (this.IsZombied)
      return (SqlConnection) null;
    return this._connection;
  }
}

I notice if the connection is closed, the transOP will become zombie, thus cannot Commit. For my case, it is because I have the Commit() inside a finally block, while the connection was in the try block. This arrangement is causing the connection to be disposed and garbage collected. The solution was to put Commit inside the try block instead.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top