2012-06-15 15 views
5

Warum verursacht dieser Code eine ungültige Operation Exception?InvalidOperationException Die Verbindung wurde nicht geschlossen. Der aktuelle Status der Verbindung ist offen

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

Vielleicht vor Ihrer Verbindung, die Sie geöffnet haben? – Zbigniew

+2

Ich denke, dass die Wurzel des Problems in der Instanz von SqlCommand im Klassenkonstruktor initialisiert ist. Wenn Sie diese Variable in Ihrem gesamten Code verwenden, kann dies leicht missbraucht werden und zu bösen Fehlern in anderen Teilen Ihres Codes führen. – Steve

+1

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

Antwort

7

Sie versuchen, eine Verbindung zu öffnen, die bereits geöffnet ist, dies in Ausnahme führt.

Lösung 1 (empfohlen):

Code Überprüfen Sie, überprüfen Sie alle Teile, bei denen cmd.Connection Verbindung geöffnet wird und sicherzustellen, dass es immer richtig geschlossen ist.

Lösung 2 (quick'n'dirty fix):

vor Zeile

cmd.Connection.Open(); 

fügen Sie die folgende Kontrolle/Bereinigungscode:

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

Bleh! Freakin Noobie Fehler. – jp2code

+0

Nun, dies könnte die Arbeit tun, aber der OP-Code beleuchtet die ExecuteNonQuery-Zeile, nicht die Connection.Open – Steve

3

Es gibt sehr wenig Notwendigkeit Halten Sie die Sql * -Objekte auf Klassenebene, insbesondere basierend auf dem, was Sie zeigen. Sie verlieren auch die Vorteile des Verbindungspoolings, indem Sie versuchen, es selbst zu tun.

Mit dieser Methode Sie die Möglichkeit, Ihre Fehler zu entfernen, weil Sie keine Gegenstände sind nicht

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; 
} 
teilen
+1

Siehe auch: http://StackOverflow.com/A/9707060/4068 –

+0

Der einzige Grund, warum ich es zuerst auf diese Weise erstellt war so, dass mehrere Teilenummern von einer einzigen Anfrage die gleiche Transaktion teilen könnten. Ich habe einen besseren Weg gefunden, dies zu tun, aber ich könnte (wahrscheinlich) diese alte Methode sowieso aufgeben. Vielen Dank. – jp2code

Verwandte Themen