2009-10-05 8 views
4

Je reçois cette erreur (transaction distribuée terminée, soit enregistrez cette session dans une nouvelle transaction ou la transaction NULL.) Lorsque j'essaie d'exécuter une procédure stockée à partir de C# sur un Base de données SQL Server 2005 Je n'utilise pas activement/volontairement des transactions ou quoi que ce soit, ce qui rend cette erreur bizarre. Je peux exécuter la procédure stockée du studio de gestion et cela fonctionne très bien. D'autres procédures stockées fonctionnent également à partir de C#, il semble que ce soit celui-ci avec des problèmes. L'erreur revient instantanément, il ne peut donc pas s'agir d'un problème de dépassement de délai. Le code est le suivant:C# SQL Transaction distribuée terminée. Soit enregistrez cette session dans une nouvelle transaction, soit la transaction NULL

SqlCommand cmd = null; 
    try 
    { 
     // Make sure we are connected to the database 
     if (_DBManager.CheckConnection()) 
     { 
     cmd = new SqlCommand(); 

     lock (_DBManager.SqlConnection) 
     { 
      cmd.CommandText = "storedproc"; 
      cmd.CommandType = System.Data.CommandType.StoredProcedure; 
      cmd.Connection = _DBManager.SqlConnection; 

      cmd.Parameters.AddWithValue("@param", value); 

      int affRows = cmd.ExecuteNonQuery(); 

      ... 
     } 
     } 
     else 
     { 
     ... 
     } 
    } 
    catch (Exception ex) 
    { 
    ... 
    } 

Ça m'a vraiment déconcerté. Merci pour toute aide

Répondre

4

On dirait qu'il y a un TransactionScope quelque part qui n'est pas satisfait. Le _DBManager.CheckConnection et _DBManager.SqlConnection sonne comme si vous gardiez un SqlConnection qui traîne, ce qui devrait contribuer à cela.

Pour être honnête, dans plupart cas courants que vous êtes mieux utiliser simplement la mise en commun de connexion intégré et using vos connexions localement - à savoir

using(var conn = new SqlConnection(...)) { // or a factory method 
    // use it here only 
} 

Ici, vous obtenez un SqlConnection propre, qui sera mis en correspondance à une connexion non gérée via le pool, c.-à-d. qu'il ne crée pas une connexion réelle chaque fois (mais fera une réinitialisation logique pour le nettoyer).

Cela permet également une utilisation beaucoup plus flexible de plusieurs threads. L'utilisation d'une connexion static dans une application Web, par exemple, serait horrible pour le blocage.

+0

La seule raison pour laquelle je garde une seule connexion est que je fais une quantité assez importante d'insertions et que je ne veux pas avoir le ralentissement de l'ouverture des connexions à chaque fois. Je vais essayer cette méthode et voir à quel point c'est rapide. N'explique toujours pas pourquoi ce code de travail ne fonctionne plus, même si rien n'a changé. – mike

+0

Oh aussi, dans Activity Monitor dans Management Studio, je peux voir 1 sous "Transactions ouvertes" pour ma connexion. Ce qui signifie qu'il y a une transaction qui traîne. Yat-il un moyen d'obtenir plus de détails sur la transaction ouverte? Merci pour l'aide. – mike

+1

Les connexions ouvertes resteront généralement dans le pool pendant la durée de vie de l'application. le tuer complètement n'est pas facile à court de désactiver la mise en commun, sacrifiant les avantages de performance de la piscine. –

0

Du code, il semble que vous utilisez une connexion déjà ouverte. Peut-être qu'une transaction est en attente précédemment sur la même connexion.

+0

Vous semblez être sur quelque chose ici. Si je ferme.() Et .Open() la connexion au début de l'appel le proc stocké fonctionne. Cela n'a pas été nécessaire dans le passé, et d'autres programmes avec le même code (mais proc différent stocké) fonctionnent toujours. Je ne peux pas trouver de code différent entre les programmes sauf le nom de proc stocké et les paramètres. J'appelle aussi déjà lecteur.Fermer(); lecteur.Dispose(); commande.Dispose(); (le cas échéant) après chaque requête. Y a-t-il un moyen de s'assurer que les transactions sont fermées? – mike

+0

Vous pourriez vouloir vérifier la procédure de magasin. Utilisez-vous une transaction à partir de là ... Ou est-il des déclencheurs sur la table qui sera par défaut à une transaction. –

+0

Dans une architecture en couches, il est toujours préférable d'implémenter l'automicité des actions au niveau de la couche logique métier. Cependant, la plupart des concepteurs de couches font leurs méthodes dal d'ouverture et de fermeture atomiques sur chaque opération dal. Si vous voulez traîner avec un problème de connexion, ouvrez une connexion sur la couche logique, puis passez-la à Dal .. De cette façon, vous aurez une trace de la connexion utilisée. D'ailleurs, en utilisant une seule connexion, puis en permettant un accès synchrone, cela diminuera les performances de votre application, ce qui est assez drastique. –

Questions connexes