sql – 使用Dapper时关闭连接

一旦查询执行显式调用Close方法或将连接放在Using语句中,是否有必要关闭连接?离开连接是否会导致连接重用并提高sql性能以备将来查询

解决方法

我假设您使用的是最新版本的Dapper.

使用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);
}

这样,您可以在一个位置控制它,而不是直接在您的调用代码中公开连接.

有关上述代码中存储库的更多详细信息,请参见here.

请注意,UnitOfWork是more,而不仅仅是一项交易.此代码仅处理事务.您可以扩展此代码以涵盖其他角色.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...