¿Es esta la forma correcta de disponer la SQLConnection?

Me preguntaba si mi implementación a continuación es la forma más eficiente de disponer la conexión SQL en este caso.

Normalmente, si uso la SqlConnection directamente, puedo envolver la conexión dentro de un bloque usando para eliminarla automáticamente, pero en este caso quería mantener la conexión abierta y disponible para todos los métodos en la clase SQLRespository.

public class SqlRepository : IRepository { private readonly string connectionString; private SqlConnection connection; public SqlRepository(string connectionString) { this.connectionString = connectionString; connection = new SqlConnection(connectionString); connection.Open(); } public void Method_A() { // uses the SqlConnection to fetch data } public void Method_B() { // uses the SqlConnection to fetch data } public void Dispose() { connection.Dispose(); } } 

Uso:

 using (IRepository repository = new SqlRepository(connectionString)) { var item = repository.items; } 

Actualizar IRepository implementa IDisposable

No mantenga la conexión abierta que abarca las llamadas. Estás derrotando la puesta en común de conexiones.

Si está trabajando con una conexión que está agrupada (como sqlserver), se agrupará y reutilizará. Solo abre y cierra dentro del método a y b.

Podría argumentar que si la persona que llama hace lo que hizo con el uso de un método, está bien. Pero si usa {} con sqlconnection dentro de cada método de trabajo (1), el código será más sencillo y (2) se asegurará de que la agrupación no se anule (lo que significa que retiene los elementos fuera de la agrupación cuando otras solicitudes podrían usarlo) .

EDITAR:

Añadiendo pseudo basado en comentarios.

El patrón es problemático porque la persona que llama puede hacerlo.

 //pseudo code using (SqlRepository r) { r.MethodA(); // other code here that takes some time. your holding a connection // out of the pool and being selfish. other threads could have // used your connection before you get a chance to use it again. r.MethodB(); } // freed for others here. 

Eso matará la escalabilidad del servidor – confía en mí. He visto sistemas muy grandes que se atragantan con esto, generalmente porque abarcan transacciones del lado AT.

Un mejor patrón:

 class Repository { void MethodA() { using (Sqlconnection) { // db call } } void MethodB() { using (Sqlconnection) { // you can even have multiple calls here (roundtrips) // and start transactions. although that can be problematic // for other reasons. } } 

Ahora, la piscina es la más efectiva. Me doy cuenta de que la pregunta era sobre el patrón desechable, y sí, puedes hacerlo. Pero …

No permitiría que la conexión abarcara la vida útil del repository.

Si quieres hacerlo así, asegúrate de implementar IDisposable (no puedo decir si notas esto en tu interfaz IRepository o no) y haré algo como:

private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { _context.Dispose(); } } this.disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } 

Obviamente, el _contexto aquí es su SqlConnection.

sin embargo, ¿está seguro de que desea una conexión por repository? ¿Qué pasa con las operaciones que abarcan más de un repository?

Suponiendo que IRepository hereda de IDisposable , su implementación está bien siempre y cuando no mantenga abierta una instancia de su clase SqlRepository durante más tiempo del necesario para realizar una secuencia “lógica” de consultas en la base de datos. El hecho de que esta secuencia pueda abarcar varias llamadas de método no es un problema.

No estoy de acuerdo con la respuesta de @ bryanmac:

No mantenga la conexión abierta que abarca las llamadas. Estás derrotando la puesta en común de conexiones.

Siempre que su secuencia de llamadas a los métodos pertenezcan juntas, y no mantenga la conexión abierta por más tiempo de lo necesario para completar la secuencia lógica, no veo cómo esto de alguna manera anula la agrupación de conexiones.

Un comentario sin embargo. Debieras:

  • O bien implemente el patrón IDisposable estándar (con un método de protected void Dispose(bool disposing) que se puede anular en clases derivadas

  • O haga que su clase esté sellada, en cuyo caso su implementación IDisposable existente está bien.