Cerrar la connection cuando se usa Dapper

¿Es necesario cerrar la connection una vez que la consulta se ejecuta explícitamente llamando al método Close o poniendo la connection dentro de la instrucción Using? ¿Dejar la connection abierta conduciría a la reutilización de la connection y mejoraría el performance de SQL para futuras consultas?

Asumo que estás usando la última versión de Dapper.

Con Dapper, hay dos forms de administrar la connection:

  • Administrate por completo: aquí, eres totalmente responsable de abrir y cerrar la connection. Así es como trata la connection mientras trabaja con ADO.NET.

  • Permita que Dapper lo administre: Dapper automáticamente abre la connection (si no se abrió) y la cierra (si fue creada por Dapper) por usted. Esto es similar al método DataAdapter.Fill() . Yo personalmente no lo recomiendo de esta manera. Esto puede no ser aplicable todo el time. A continuación se muestra lo que Marc Gravell dice en uno de los comentarios para esta respuesta: https://stackoverflow.com/a/12629170/5779732

bien, técnicamente abierto / cerrado es diferente a lo dispuesto. Si solo vas a estar abriendo / cerrando alnetworkingedor de las llamadas individuales, también puedes dejar que apresuradamente lo hagas. Si está abriendo / cerrando en una granularidad más amplia (por request, por ejemplo), sería mejor para su código hacerlo y pasar una connection abierta a apuesto.

Por supuesto, puede llamar a múltiples consultas en una sola connection. Pero la connection debe cerrarse (llamando al método Close() , Dispose() o encerrándola using bloque) para evitar la pérdida de resources. La connection de cierre lo devuelve al grupo de conexiones. La participación del grupo de conexiones mejora el performance sobre el nuevo costo de connection.


Además de solo manejar la connection, le sugiero que implemente UnitOfWork para administrar las transactions también. Refiera esta excelente muestra en GitHub.

El siguiente código fuente puede ayudarte. Tenga en count que esto está escrito para mis necesidades; por lo que puede no funcionar para usted como es.

 public sealed class DalSession : IDisposable { public DalSession() { _connection = new OleDbConnection(DalCommon.ConnectionString); _connection.Open(); _unitOfWork = new UnitOfWork(_connection); } IDbConnection _connection = null; UnitOfWork _unitOfWork = null; public UnitOfWork UnitOfWork { get { return _unitOfWork; } } public void Dispose() { _unitOfWork.Dispose(); _connection.Dispose(); } } public sealed class UnitOfWork : IUnitOfWork { internal UnitOfWork(IDbConnection connection) { _id = Guid.NewGuid(); _connection = connection; } IDbConnection _connection = null; IDbTransaction _transaction = null; Guid _id = Guid.Empty; IDbConnection IUnitOfWork.Connection { get { return _connection; } } IDbTransaction IUnitOfWork.Transaction { get { return _transaction; } } Guid IUnitOfWork.Id { get { return _id; } } public void Begin() { _transaction = _connection.BeginTransaction(); } public void Commit() { _transaction.Commit(); Dispose(); } public void Rollback() { _transaction.Rollback(); Dispose(); } public void Dispose() { if(_transaction != null) _transaction.Dispose(); _transaction = null; } } interface IUnitOfWork : IDisposable { Guid Id { get; } IDbConnection Connection { get; } IDbTransaction Transaction { get; } void Begin(); void Commit(); void Rollback(); } 

Ahora, sus repositorys deberían aceptar este UnitOfWork de alguna manera. Elijo Inyección de dependencia con Constructor.

 public sealed class MyRepository { public MyRepository(IUnitOfWork unitOfWork) { this.unitOfWork = unitOfWork; } IUnitOfWork unitOfWork = null; //You also need to handle other parameters like 'sql', 'param' ect. This is out of scope of this answer. public MyPoco Get() { return unitOfWork.Connection.Query(sql, param, unitOfWork.Transaction, .......); } public void Insert(MyPoco poco) { return unitOfWork.Connection.Execute(sql, param, unitOfWork.Transaction, .........); } } 

Y luego lo llamas así:

Con la transacción:

 using(DalSession dalSession = new DalSession()) { UnitOfWork unitOfWork = dalSession.UnitOfWork; unitOfWork.Begin(); try { //Your database code here MyRepository myRepository = new MyRepository(unitOfWork); myRepository.Insert(myPoco); //You may create other repositories in similar way in same scope of UoW. unitOfWork.Commit(); } catch { unitOfWork.Rollback(); throw; } } 

Sin transacción:

 using(DalSession dalSession = new DalSession()) { //Your database code here MyRepository myRepository = new MyRepository(dalSession.UnitOfWork);//UoW have no effect here as Begin() is not called. myRepository.Insert(myPoco); } 

De esta manera, en lugar de exponer directamente la connection en su código de llamada, la controla en una location.

Más detalles sobre el repository en el código anterior se pueden encontrar aquí .

Tenga en count que UnitOfWork es más que solo una transacción. Sin embargo, este código solo maneja transactions. Puede extender este código para cubrir roles adicionales.