Skip to content

Instantly share code, notes, and snippets.

@TristanOrta
Last active December 15, 2023 19:43
Show Gist options
  • Save TristanOrta/d5e9777bc06bac32b34d6a143a63380c to your computer and use it in GitHub Desktop.
Save TristanOrta/d5e9777bc06bac32b34d6a143a63380c to your computer and use it in GitHub Desktop.
C# no cierra sesión de Oracle al terminar de hacer una transacción

Cerrar conexion en base de datos oracle ( eliminar sesion )

Normalmente, cuando hacemos una conexión a Oracle desde C#, usamos una cadena de conexión como la siguiente:

string sqlconn = $"Data Source={server}; Password={password}; USER ID={user};";

Al momento de hacer la conexión, se utiliza el método Open de la librería de conexión:

conexion.Open();

Naturalmente, al momento de cerrar, se utiliza Close:

conexion.Close();

El detalle es que al hacer un SELECT en la vista v$session de Oracle, podríamos ver la sesión aún activa a pesar de haber cerrado la conexión:

SELECT osuser, username, machine, program, status, sid, serial# FROM v$session ORDER BY osuser;
SELECT a.USERNAME, a.SID, a.SERIAL#, b.SPID, a.PROGRAM, a.OSUSER
FROM v$session a, v$process b
WHERE a.PADDR = b.ADDR
ORDER BY 1;

Las consultas se verían algo así:

USERNAME SID SERIAL# SPID PROGRAM OSUSER
MyUserORacle 74 255 11827 MiAppC#.exe MyOSUser
OtherUserORacle 97 9 20075 otherApp.exe OtherOSUser

Como se ve, MiAppC#.exe tiene la sesión aún abierta a pesar de usar la función Close en mi código. ¿Por qué pasa esto?

Indirectamente, estamos dejando un pool de conexión abierto. Esto ocurre porque la cadena de conexión es única y, al momento de crearla, la mantiene activa para que, si se requiere alguna otra conexión, el sistema pueda reutilizar el pool anterior y que esta comunicación sea más rápida. Digamos que mantiene ese canal abierto por si se requiere. Después de un tiempo determinado, cierra la conexión por completo.

Se puede eliminar esta conexión manualmente desde la BD con ALTER SYSTEM KILL SESSION '74, 225'; , pero el registro permanecerá por algún tiempo en v$session con un status de "Killed".

Estos son los tipos de status:

ACTIVO: Sesión actualmente ejecutando SQL.
INACTIVO: Inactivo.
KILLED: Sesión marcada para ser eliminada.
CACHED: Sesión almacenada temporalmente en caché para uso de Oracle*XA.
SNIPED: Sesión inactiva, esperando al cliente.

Por lo tanto, "Killed" hará que el registro permanezca en la vista algún tiempo más.

Ahora, ¿cómo podemos eliminar esta sesión por completo desde el inicio sin dejar el pool abierto en espera de alguna conexión?

Fácil, se necesita de la siguiente cadena de conexión:

string sqlconn = $"Data Source={server}; Password={password}; USER ID={user}; pooling=false;";

Donde explícitamente indicamos que el pool o pooling debe ser igual a "false".

Aquí ya no cerraremos con un Close, sino con un Dispose:

conexion.Dispose();

Así evitamos dejar conexiones abiertas.

La desventaja es que si tu aplicación genera muchas transacciones de manera continua, al estar creando conexiones nuevas y no reutilizando las existentes, volverá los tiempos de respuesta más lentos, creando problemas de rendimiento. Pero es perfecto cuando tu aplicación, por ejemplo, es un código que envía un informe por correo una vez al día, ya que la conexión no se volverá a usar hasta el día siguiente.

Saludos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment