Pregunta

Yo estaba tratando de explicarle a alguien qué conexiones base de datos implementar IDisposable, cuando me di cuenta que no se sabe muy bien lo que "la apertura de una conexión" significa realmente.
Así que mi pregunta es - ¿Qué c # prácticamente hacer cuando se abre una conexión?

Gracias.

¿Fue útil?

Solución

En realidad, hay dos clases involucradas en la implementación de una conexión (en realidad más, pero estoy simplificando).

Uno de ellos es la aplicación IDbConnection (SQLConnection, NpgsqlConnection, OracleConnection, etc.) que se utiliza en el código. El otro es un objeto de conexión "real" que es interno a la asamblea, y no es visible para el código. Llamaremos a este "RealConnection" por ahora, aunque su nombre real es diferente con distintas implementaciones (por ejemplo, en Npgsql, que es el caso en el que estoy más familiarizado con la implementación, la clase se llama NpgsqlConnector).

Al crear su IDbConnection, que no tiene un RealConnection. Cualquier intento de hacer algo con la base de datos fallará. Cuando Open() entonces ocurre lo siguiente:

  1. Si se habilita la puesta en común, y hay una RealConnection en la piscina, deque y hacer que la RealConnection para la IDbConnection.
  2. Si se habilita la puesta en común, y el número total de objetos RealConnection en la existencia es más grande que el tamaño máximo, una excepción.
  3. De lo contrario crear una nueva RealConnection. Inicializar, lo que implicará la apertura de algún tipo de conexión de red (por ejemplo, TCP / IP) o identificador de archivo (por algo así como acceso), pasar por el protocolo de la base de datos para el apretón de manos (varía según el tipo de base de datos) y autorizar la conexión. Este se convierte en el RealConnection para la IDbConnection.

Las acciones llevadas a cabo en el IDbConnection se convierten en las operaciones de la RealConnection hace en su conexión a la red (o lo que sea). Los resultados se convirtieron en objetos de aplicación IDataReader y así sucesivamente con el fin de darle una interfaz consistente para su programación.

Si un IDataReader fue creado con CommandBehavior.CloseConnection, después de que datareader obtiene la "propiedad" de la RealConnection.

Cuando se llama a Close() entonces uno de ocurre lo siguiente:

  1. Si la puesta en común, y si la piscina no está llena, entonces el objeto se coloca en la cola para su uso con las operaciones posteriores.
  2. lo contrario, el RealConnection llevará a cabo los procedimientos definidos en el protocolo para poner fin a la conexión (de señalización a la base de datos que la conexión se va a cerrar) y cierra la conexión de red etc. El objeto puede entonces caer fuera del alcance y estén disponibles para la recolección de basura.

La excepción sería si el caso CommandBehavior.CloseConnection sucedió, en cuyo caso de Close() o Dispose() siendo llamado en el que los desencadenantes IDataReader esto.

Si llama Dispose() entonces sucede lo mismo según Close(). La diferencia es que Dispose() se considera como "limpieza" y puede trabajar con using, mientras Close() podría utilizarse en el medio de toda la vida, y seguido por un Open() más tarde.

Debido al uso del objeto RealConnection y el hecho de que ellos se reúnen, apertura y cierre de conexiones cambios de ser algo relativamente pesado a relativamente ligero. Por lo tanto, en lugar de ser importante mantener conexiones abiertas durante mucho tiempo para evitar la sobrecarga de abrirlos, se convierte en importante para mantenerlos abiertos durante el tiempo de un corto como sea posible, ya que las ofertas RealConnection con la sobrecarga para usted, y cuanto más rápidamente los usa, más eficientemente las conexiones agrupadas se comparten entre usos.

Tenga en cuenta también, que está bien para un Dispose() IDbConnection que ya ha llamado Close() en (que es una regla que siempre debe ser seguro para llamar Dispose(), cualquiera que sea el estado, de hecho, incluso si ya se llamaba). Por tanto, si estuviera llamando manualmente Close() aún sería bueno tener la conexión en un usingbloque, para coger los casos en que excepciones ocurren antes de la llamada a Close(). La única excepción es donde realmente se desea que la conexión permanezca abierta; Digamos que ha devolver un IDataReader creada con CommandBehavior.CloseConnection, en cuyo caso no se deshaga el IDbConnection, pero no disponer el lector.

En caso de no disponer de la conexión, entonces el RealConnection no será devuelta a la piscina para su reutilización, o ir a través de su procedimiento de apagado. A la piscina alcanzará su límite, o el número de conexiones subyacentes se incrementará hasta el punto de dañar el rendimiento y el bloqueo de más que se creen. Eventualmente, el finaliser en RealConnection puede ser llamado y el plomo a este ser fijo, pero la finalización sólo reduce el daño y no se puede confiar. (El IDbConnection no necesita un finaliser, ya que es la RealConnection que sostiene el recurso no administrado y / o necesidades para hacer el apagado).

También es razonable suponer que hay algún otro requisito para la disposición única para la aplicación de la IDbConnection más allá de esto, y todavía debe desecharse incluso si el análisis de lo anterior conduce a creer que no es necesario (la excepción es cuando CommandBehavior.CloseConnection pasa toda la carga disposición para la IDataReader, pero entonces es tan importante para disponer que el lector).

Otros consejos

Buena pregunta.

Desde mi (conocimiento tanto limitada) del "bajo el capó" de trabajo de una conexión de SQL, muchos pasos están involucrados, como por ejemplo:

los pasos bajo el capó

  1. socket Física / tubo se abre (el uso de controladores dado, por ejemplo ODBC)
  2. apretón de manos con SQL Server
  3. Cadena de conexión / credenciales negociado
  4. ámbito de las transacciones

Por no hablar de la agrupación de conexiones, creo que hay algún tipo de alogrithm involucrados (si la cadena de conexión coincide con uno de una piscina ya existente, se añade la conexión a la piscina, de lo contrario se crea uno nuevo)

IDiposable

En cuanto a conexiones SQL, que implementar IDisposable para que cuando llamamos a dispose (ya sea a través de la directiva using o explícitamente), coloca la parte posterior de conexión en la agrupación de conexiones. Esto está en marcado contraste con sólo el SQLConnection.close simple y llano () -. Como todo esto hace es estrecha temporalmente, pero las reservas de esa conexión para su uso posterior

A mi entender, .Close () cierra la conexión a la base de datos, mientras que .Dispose () llama .Close (), y después Comunicados de recursos no administrados.

Estos puntos en mente, por lo menos, es una buena práctica para implementar IDisposable.

Añadir a respuestas anteriores ... La clave es que al "abrir la conexión" se pueden asignar recursos que se requerirán más de la recolección de basura estándar para recuperar, a saber, un socket abierto / tubería / IPC de somekind. El método Dispose () limpia estas arriba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top