一旦显式调用Close方法或将连接放入Using语句,是否需要关闭连接?离开连接是否会导致连接重用并提高SQL性能以用于将来的查询?使用Dapper时的关闭连接
4
A
回答
11
我假设您使用的是最新版本的Dapper。
凭借小巧玲珑的,有管理的连接方式有两种:
全面管理自己: 在这里,你是打开和关闭连接承担全部责任。这就像您在使用ADO.NET时对待连接的方式一样。
允许小巧玲珑来管理: 小巧玲珑的自动打开的连接(如果它没有打开),并关闭它(如果它是由小巧玲珑开业)为您服务。这与
DataAdapter.Fill()
方法类似。我个人不建议这样。这可能不适用于每次。以下就是马克Gravell说,在comment此答案之一:https://stackoverflow.com/a/12629170/5779732
很好,技术上打开/关闭是处置不同。如果你只打算打开/关闭个人电话,那么你可以让精巧的人来做。 如果您打开/关闭更广的粒度(例如,每个请求),那么对您的代码执行此操作并将打开的连接传递给Dapper会更好。
当然,您可以在单个连接上调用多个查询。但是,应该关闭连接(通过调用Close()
,Dispose()
方法或将其封装在using
块中)以避免资源泄漏。关闭连接将其返回到连接池。连接池的参与提高了新连接成本的性能。
除了只处理连接,我建议你实现UnitOfWork来管理事务。请参阅this GitHub上的优秀示例。
以下源代码可能对您有所帮助。请注意,这是为我的需要而编写的;所以它可能不适合你。
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。我用构造函数选择依赖注入。
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, .........);
}
}
然后调用它像这样:
随着交易:
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);
}
这种方式,而不是直接暴露在你的呼叫连接代码,你可以在一个位置控制它。
有关上述代码中有关Repository的更多详细信息,请参阅here。
请注意,UnitOfWork
是more而不仅仅是交易。尽管这个代码只处理事务。您可以扩展此代码以涵盖其他角色。
相关问题
- 1. 使用LdapTemplate时LDAP连接未关闭
- 2. mysql_pconnect()连接何时关闭
- 3. 使用LINQ关闭与DB的连接?
- 4. 连接关闭时,ODP.net是否关闭了引用游标?
- 5. PHP:关闭套接字连接时,网页关闭
- 6. 使用HTTP Servlets中的连接池关闭连接的位置
- 7. ajax调用关闭连接
- 8. 用扭曲关闭连接
- 9. 使用“使用”语句时是否需要关闭连接
- 10. 何时关闭PHP中的连接?
- 11. Signalr关闭连接
- 12. 关闭SQLDataSource连接
- 13. 关闭oracle连接
- 14. 关闭SOAP连接
- 15. MongoEngine:关闭连接
- 16. 关闭WCF连接
- 17. Pgbouncer关闭连接
- 18. nodejs。关闭连接
- 19. java.sql.SQLRecoverableException:关闭连接
- 20. SoapUI连接关闭
- 21. 使用urlretrieve后关闭ftp连接
- 22. 在Dapper中使用存储库模式时,是否需要打开和关闭数据库连接?
- 23. 何时使用Java servlets打开和何时关闭mysql连接?
- 24. 使用grails中的groovy.sql.newInstance - 关闭连接以及何时?
- 25. 关闭或不关闭Oracle连接?
- 26. WCF-“底层连接已关闭:连接意外关闭”
- 27. 底层连接已关闭:连接意外关闭wcf
- 28. 底层连接已关闭:连接意外关闭#2
- 29. 底层连接已关闭:连接意外关闭 - wcf
- 30. WP7 WCF底层连接已关闭:连接意外关闭
我不能完全同意你对你的第二意见。有时让精巧的管理连接是一个更好的选择。我想引用来自https://stackoverflow.com/a/12629170/1262198: 的Marc Gravell“技术上的开放/关闭与处置不同,如果您只打算打开/关闭个别通话,您可能会如果你以更大的粒度打开/关闭(比如每个请求),最好让你的代码做到这一点,并将打开的连接传递给Dapper。“ – Arvand
@Arvand:同意。我纠正了我的答案。我只是说这可能不适用于每一次。 –