2009-06-06 11 views
6

En Java y C#, ambos tienen algo así como System.terminate(). Si mi programa tiene conexiones de bases de datos abiertas, lectores de bases de datos y variables de comandos de bases de datos, y termino mi programa en una cláusula de captura, ¿los recursos de la base de datos seguirán en uso? o serán liberados automáticamente ya que mi programa completo acaba de salir?Si un programa de consola termina, ¿las conexiones a la base de datos utilizadas en el programa permanecerán abiertas?

Normalmente, ¿cómo debo manejar estos casos para asegurarme de que siempre libero las conexiones a la base de datos, ya sea a través de la terminación normal del programa o la terminación inesperada del programa? ¿Alguna buena práctica?

Respuesta

0

En C#, que normalmente estrechas conexiones inmediatamente después de su uso, por ejemplo:

using(SqlConnection connection = ...) 
{ 
    ... do something ... 
} // connection disposed/closed here 

Sin embargo, normalmente utilizará un grupo de conexiones, y todo lo que hace es devolver la conexión al grupo. Por lo tanto, su proceso seguirá teniendo conexiones activas con el servidor de la base de datos.

Si se apaga limpiamente, sin duda se limpiará el conjunto de conexiones y se cerrarán las conexiones reales a la base de datos (puede verificar esto mirando las conexiones abiertas en el servidor de la base de datos).

Pero existen situaciones (por ejemplo, llamar a Environment.FailFast) en las que la aplicación puede bloquearse sin necesidad de cerrar las conexiones; en este caso, con el tiempo el servidor de la base de datos se cerrará y cerrará.

+0

¿Se puede expandir en el grupo de conexiones? ¿Y cómo los implementaría? – Saobi

5

A menos que cierre específicamente la conexión, permanecerán abiertos hasta que se agote el tiempo de espera.

He encontrado esto por las malas en C# algunas veces. Las mejores prácticas dictan cerrar/cerrar recursos que sabe que ya no necesitará. Archivo E/S, conexiones DB, etc. etc.

+0

¿Eso es cierto incluso si la aplicación falla? (No siendo gracioso, simplemente curioso) –

+1

Me lo imagino. Quiero decir, si tienes un try/catch y estabas en el medio de editar un archivo y tiré del cable de alimentación. Esas salvaciones se perderán en el limbo .... –

+0

Creo que esto depende del tipo de bloqueo. Ciertos bloqueos pueden afectar el tiempo de ejecución (como tirar del cable de alimentación, desbordamientos de pila, etc.) por lo que en ese caso, la conexión permanecerá abierta hasta que se agote el tiempo de espera. Sin embargo, si se lanza una excepción simple, creo que el tiempo de ejecución aún intentará cerrar la conexión (si está en un bloque 'finally') –

6

Al finalizar un proceso, todos los recursos asociados (incluida la memoria, identificadores, conexiones, ...) se liberarán.

Normalmente, en C#, usará la declaración Dispose pattern/using para controlar los recursos escasos.

+1

Según tengo entendido, creo que tienes razón. Lo que me parece curioso es que PSU_Kardi afirma lo contrario y tiene más votos positivos. Entonces, ¿quién tiene razón? –

+0

@MasterPeter: Esto definitivamente depende de la plataforma. Pero en la mayoría de los sistemas principales que he visto, este es el caso. –

+0

Corrección de pedidos pendientes corregida. –

-1

Debe borrarse en el siguiente GC, pero para ser precisos, en C# puede cerrar la conexión en el bloque final del manejo estructurado de excepciones.

try { 
    // open DB connection 
} catch (Exception ex) { 
    // deal with exception 
} finally { 
    // close and dispose connection 
} 
+0

Ok. pero ¿y si tengo declaraciones de conexión DB extendidas a lo largo de mi programa, por lo que no puedo juntarlas en una try/catch/finally? ¿Debo simplemente poner mi programa ENTERO en un gran bloque try/catch/finally, entonces cada vez que ocurra un error inesperado mi db se cerrará? Pero poner todo en un gran try/catch/finally ¿no es gracioso? – Saobi

+0

Errr ... ¿dónde está el GC cuando el proceso no existe? –

+1

Saobi: debe dividir el código DB en fragmentos más manejables y poner try/catch block en cada uno. Curt: esto es ANTES de que finalice el proceso, mejor que simplemente terminar el proceso porque no se puede garantizar que la terminación anormal siempre cierre la conexión. –

0

El comportamiento general de POSIX es que, cuando finaliza el programa, todos los manejadores de archivos, las conexiones de red, etc. se cierran. Si el otro extremo hace lo correcto en ese punto es una pregunta abierta, pero si está utilizando cualquier RDBMS razonablemente popular, estará bien.

1

En C#, la limpieza implícita se realiza por el recolector de elementos no utilizados si se implementa un finalizador en el objeto que se recoge como basura. Cualquier limpieza de recursos no administrados, como las conexiones de bases de datos, se puede hacer en el método Dispose.

Consulta este artículo para obtener más información:

Ejecución finalizar y Dispose para limpiar no administrado Recursos
http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx

1

Cuando finaliza un proceso, todos los descriptores de archivos que tiene abiertos deben ser liberados por el sistema operativo. Las descripciones de archivos incluyen archivos y sockets, que generalmente cubrirán las conexiones de su base de datos.

Todo lo que le dice es que cuando su cliente finaliza sus conexiones están cerradas. No te dice lo que hace el servidor. Dependiendo de cómo esté escrito, es muy posible que el servidor continúe manteniendo sus conexiones abiertas, esperando mensajes del cliente que nunca llegarán, o incluso intentando enviar datos. Es probable que estos finalicen con el tiempo, pero esto podría no estar bien planeado. (Debería ser, para un RDBMS decente, pero podría no serlo). De modo que, dependiendo de su RDBMS, es posible que deba realizar algunos pasos para indicarle al servidor que está bajando que le diga que libere sus recursos.

1

Si está trabajando con SQL Server puede echar un vistazo a sysprocesses o ejecutar sp_who2. He probado esto en mi máquina y las conexiones no se cierran, es decir:

Console.Write("Opening connection"); 
Console.ReadLine(); 
SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=SeniorMail;Integrated Security=SSPI;"); 
connection.Open(); 
SqlCommand command = new SqlCommand("SELECT count(*) from Account", connection); 
Console.Write("Running sql"); 
Console.ReadLine(); 
int? count = command.ExecuteScalar() as int?; 
Console.Write("Now I'll throw an exception"); 
Console.ReadLine(); 
int a = 0, b = 1, c = 0; 

try 
{ 
    c = b/a; 
} 
catch 
{ 
    Environment.Exit(1); 
} 

He comprobado sp_who2 cada lado de "Ahora voy a tirar una excepción", y puedo ver la conexión ha desaparecido después de la aplicación salidas.

Cuestiones relacionadas