解决方法
使用Dapper,有两种方法可以管理连接:
>全面管理自己:
在这里,您完全负责打开和关闭连接.这就像您在使用ADO.NET时处理连接一样.
>允许Dapper管理它:
Dapper会自动打开连接(如果没有打开)并为您关闭它(如果它是由Dapper打开的).这类似于DataAdapter.Fill()方法.我个人不推荐这种方式.这可能不适用于每次.以下是Marc Gravell在comment中的一个中所说的答案:https://stackoverflow.com/a/12629170/5779732
well,technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls,you might as well let dapper do it. If you are opening/closing at a wider granularity (per request,for example),it would be better for your code to do it and pass an open connection to dapper.
当然,您可以在单个连接上调用多个查询.但是,应该关闭连接(通过调用Close(),Dispose()方法或将其封闭在使用块中)以避免资源泄漏.关闭连接会将其返回到连接池.连接池的参与提高了新连接成本的性能.
除了处理连接之外,我建议你实现UnitOfWork来管理事务.在GitHub上参考this优秀样本.
以下源代码可以帮助您.请注意,这是为了我的需要而写的;所以它可能不适合你.
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(); }
现在,您的存储库应该以某种方式接受此UnitOfWork.我选择了使用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,.........); } }
然后你这样称呼它:
随着交易:
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; } }
没有交易:
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); }