【问题标题】:Ensuring the database connection opens and closes every time I use Dapper to access the database确保每次使用 Dapper 访问数据库时打开和关闭数据库连接
【发布时间】:2015-06-23 21:15:22
【问题描述】:

这是我目前在我的一个存储库类中所做的:

private IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString);

public IEnumerable<Product> GetProducts(int categoryId = null, bool? active = null)
{
    StringBuilder sql = new StringBuilder();
    sql.AppendLine("SELECT * ");
    sql.AppendLine("FROM Product ");
    sql.AppendLine("WHERE @CategoryId IS NULL OR CategoryId = @CategoryId ");
    sql.AppendLine("  AND @Active IS NULL OR Active = @Active");

    return this.db.Query<Product>(sql.ToString(), new { CategoryId = categoryId, Active = active }).ToList();
}

我想做的一件事是将 IDbConnection 属性放在 BaseRepository 中,我的所有其他 repos 都继承自该 BaseRepository。我该怎么做才能确保我的数据库连接在我的每个数据访问功能(如上面的示例)中正确打开和关闭?这是我目前对 Entity Framework 所做的事情(每个函数都有一个 using 语句,但现在我将 DAL 切换为使用纯 Dapper:

using (var context = new MyAppContext())
{
    var objList = (from p in context.Products
                   where (categoryId == null || p.CategoryId == categoryId) &&
                         (active == null || p.Active == active)
                   select p).ToList();

    return objList;
}

我注意到在 Dapper examples 中,所有内容都像我所期望的那样包装在 using 语句中,但偶尔我会看到他们将其函数包装在以下 using 中:

using (var connection = Program.GetClosedConnection())

GetClosedConnection()返回一个新的SqlConnection,但是两者有什么区别呢?

public static SqlConnection GetOpenConnection(bool mars = false)
{
    var cs = connectionString;
    if (mars)
    {
        SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(cs);
        scsb.MultipleActiveResultSets = true;
        cs = scsb.ConnectionString;
    }
    var connection = new SqlConnection(cs);
    connection.Open();
    return connection;
}
public static SqlConnection GetClosedConnection()
{
    return new SqlConnection(connectionString);
}

【问题讨论】:

    标签: c# sql sql-server database-connection dapper


    【解决方案1】:

    这就是我一直这样做的方式:

    SqlConnection dbConnection;
    using (dbConnection = new SqlConnection(connectionString))
    {
        /* 
           Whatever Dapper stuff you want to do. Dapper will open the
           connection and the using will tear it down.
        */
    }
    

    至于问题的第二部分,GetClosedConnection 只是实例化了一个 SqlConnection 对象,而 GetOpenConnection 实例化了并打开一个 SqlConnection 对象。您(或 Dapper)将不得不手动调用 Open()GetClosedConnection 返回的对象。

    【讨论】:

    • 这看起来像我想要的。尽管我试图避免在我的所有存储库中重复,所以我想创建一个已经包含 dbConnection 的基本存储库。但我想这是我能做到的,那么我会在你的例子中简单地使用 using 语句。还有其他想法吗?
    • Dapper 原生使用 SqlConnection 对象,Microsoft 明确建议使用 using 语句管理 SqlConnections。这是因为SqlConnections 在超出范围时不会关闭。您可以在基本存储库中编写一个包装器来执行一般查询,但无论您在哪里执行,最佳做法是将您的 SqlConnection 包装在 using 块中。
    【解决方案2】:

    此答案将基于您“避免重复”的愿望。

    创建一个 Dapper 的扩展类并将函数放入其中并改用它。像这样:

        public IEnumerable<T> Query<T>(string sqlQuery, object parameters = null)
        {
            this.activeConnection.Open();
    
            var result = this.activeConnection
                .Query<T>(sqlQuery, parameters);
    
            this.activeConnection.Close();
    
            return result;
        }
    

    在类的顶部放一个

        public SqlConnection activeConnection { get; private set; }
    

    它总是在类的构造函数中设置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-31
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      相关资源
      最近更新 更多