2012-06-15 36 views
5

¿Por qué este código arroja una excepción de operación no válida?InvalidOperationException La conexión no se cerró. El estado actual de la conexión está abierto

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

Tal vez usted haya abierto su conexión antes? – Zbigniew

+2

Creo que la raíz del problema está en la instancia de SqlCommand inicializado en el constructor de la clase. Tener esta var alrededor en todo su código podría ser mal utilizado fácilmente y conducir a errores desagradables en otras partes de su código – Steve

+1

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

Respuesta

7

usted está tratando de abrir una conexión que ya está abierto, esto da lugar a una excepción.

Solución 1 (recomendado):

inspeccionar su código, revise todas las partes donde se abre cmd.Connection conexión y asegurar que siempre está cerrada correctamente.

Solución 2 (solución quick'n'dirty):

antes de la línea

cmd.Connection.Open(); 

añadir el siguiente código de verificación/limpieza:

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

Bleh! Freakin 'noobie errors. – jp2code

+0

Bueno, esto podría hacer el trabajo, sin embargo, el código OP resalta la línea ExecuteNonQuery, no Connection.Open – Steve

3

Hay muy poca necesidad de manteniendo los objetos Sql * en el nivel de clase, especialmente en función de lo que se muestra. También perderá los beneficios de la agrupación de conexiones al intentar hacerlo usted mismo.

Con este método, se elimina la posibilidad de que su error porque usted no está compartiendo ningún objeto

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

Vea también: http://stackoverflow.com/a/9707060/4068 –

+0

La única razón por la que inicialmente lo creé de esta manera fue para que varios números de parte de una sola solicitud pudieran compartir la misma transacción. Sin embargo, he encontrado una forma mejor de hacerlo, así que podría (probablemente debería) abandonar este viejo método de todos modos. Gracias. – jp2code

Cuestiones relacionadas