2012-06-15 4 views
5

Pourquoi ce code lance-t-il une exception d'opération non valide?InvalidOperationException La connexion n'a pas été fermée. L'état actuel de la connexion est ouvert.

private SqlCommand cmd; // initialized in the class constructor 

public void End(string spSendEventNotificationEmail) { 
    try { 
    cmd.CommandText = spSendEventNotificationEmail; 
    cmd.Parameters.Clear(); 
    cmd.Parameters.Add("@packetID", SqlDbType.Int).Value = _packetID; 
    cmd.Parameters.Add("@statusID", SqlDbType.Int).Value = _statusID; 
    cmd.Parameters.Add("@website", SqlDbType.NVarChar, 100).Value = Tools.NextStep; 
    cmd.Connection.Open(); 
    cmd.ExecuteNonQuery(); 
    } finally { 
    cmd.Connection.Close(); 
    cmd.Parameters.Clear(); 
    cmd.Dispose(); 
    } 
    endCall = true; 
} 

InvalidOperationException

+1

Peut-être que vous avez ouvert votre connexion avant? – Zbigniew

+2

Je pense que la racine du problème est dans l'instance de SqlCommand initialisée au constructeur de la classe. Ayant cette var autour de tout votre code pourrait être facilement utilisé à mauvais escient et conduisant à des bogues méchants dans d'autres parties de votre code – Steve

+1

http://stackoverflow.com/a/9707060/4068 –

Répondre

7

Vous essayez d'ouvrir une connexion qui est déjà ouvert, il en résulte une exception.

Solution 1 (recommandé):

votre code Inspectez, vérifiez toutes les pièces où la connexion cmd.Connection est ouverte et assurez-vous qu'il est toujours fermé.

Solution 2 (quick'n'dirty fixe):

avant la ligne

cmd.Connection.Open(); 

ajouter le code de contrôle/nettoyage suivant:

if (cmd.Connection.State == ConnectionState.Open) 
{ 
    cmd.Connection.Close(); 
} 
+1

Bleh! Freakin 'noobie erreurs. – jp2code

+0

Eh bien, cela pourrait faire le travail, mais le code OP éclaire la ligne ExecuteNonQuery, pas le Connection.Open – Steve

3

Il y a besoin de très peu Garder les objets Sql * au niveau de la classe, surtout en fonction de ce que vous montrez. Vous perdrez également les avantages de la mise en commun des connexions en essayant de le faire vous-même.

Avec cette méthode, vous supprimez la possibilité de votre erreur parce que vous n'êtes pas partager des objets

private readonly _connectionString = "..."; 

public void End(string spSendEventNotificationEmail) { 
    using(var conn = new SqlConnection(_connectionString)) 
    using(var cmd = conn.CreateCommand()) 
    { 
    cmd.CommandText = spSendEventNotificationEmail; 
    cmd.Parameters.Add("@packetID", SqlDbType.Int).Value = _packetID; 
    cmd.Parameters.Add("@statusID", SqlDbType.Int).Value = _statusID; 
    cmd.Parameters.Add("@website", SqlDbType.NVarChar, 100).Value = Tools.NextStep; 
    conn.Open(); 
    cmd.ExecuteNonQuery(); 
    } 
    endCall = true; 
} 
+1

Voir aussi: http://stackoverflow.com/a/9707060/4068 –

+0

La seule raison pour laquelle je l'ai initialement créé de cette façon était de sorte que plusieurs numéros de pièce d'une même demande puissent partager la même transaction. J'ai trouvé une meilleure façon de faire cela, donc, je pourrais (probablement devrait) abandonner cette vieille méthode de toute façon. Merci. – jp2code

Questions connexes