有关C#里数据库连接释放的问题

.Net技术 码拜 8年前 (2016-05-06) 2911次浏览
如题,与数据库的连接进行SQL查询的方法,我们都希望能设计为一个公有的静态方法,然而在使用有返回结果的查询时,数据库的连接对象却不应该立即被释放掉。

        public static SqlDataReader Execute(String sql) {
            SqlConnection conn = new SqlConnection(Constants.CONNECT_STRING);
                using(SqlCommand cmd = new SqlCommand(sql, conn)) {
                    try {
                        conn.Open();
                        return cmd.ExecuteReader();
                    } catch(System.Data.SqlClient.SqlException ex) {
                        throw new Exception(ex.Message);
                    }
                }
        }

以上方法执行一个带有返回值的SQL查询,查询后,为了使得该方法的结果SqlDataReader能够被调用者所继续使用,所以不能够在这个方法里使用using自动释放SqlConnection conn。
那么在调用者处的代码写为

SqlDataReader sdr = SQLHelper.Execute(sql);
// 使用sdr
sdr.Close();
sdr = null;

这样可以确保立即释放SqlDataReader,但是这样能确保SqlConnection conn也被释放吗,假如SqlConnection conn没有被释放应该怎么做?
本人能否可以设计一个结构(假设类名为Result),将conn和sdr放在一起同时作为Execute方法的返回值,然后在调用者的代码使用完sdr后,写

Result ret = SQLHelper.Execute(sql);
// 使用ret.sdr
ret.sdr.Close();
ret.sdr = null;
ret.conn.Close();
ret.conn.Dispose();
ret.conn = null;

问一下本人这样的设计合理吗,还是说可以完全不用去管SqlConnection conn何时以及怎么样被释放呢,没记错的话这个叫非托管资源

解决方案

15

假如你在打开 DbDataReader 时提供 CommandBehavior.CloseConnection 为值得参数,那么它执行 Close 时就会把传给它的 DbConnection 也给 Close。
但是,这样你就无法使用 Using{…} 结构来保证任何时候都自动关闭,而需要注意手写代码。而只要是靠人“自觉”的做法,就不可靠。自动化的做法才行。
所以更好的方式,是不要使用 DataReader 作为输出。例如

public static List<T> GetList<T>(string connectionString, SqlCommand cmd, Func<IDataReader, T> Converter)
{
    using (var conn = new SqlConnection(connectionString))
    {
        conn.Open();
        return (from IDataReader rd in cmd.ExecuteReader() select Converter(rd)).ToList();
    }
}

可以发返回强类型的对象集合,例如调用它

public class ResultType
{
    public string Name;
    public decimal Cost;
}
var lst = SqlHelper.GetList<ResultType>(string, cmd,
        rd => new ResultType
        {
            Name = (string)rd["Name"],
            Cost = (decimal)rd["Cost"]
        });

5

SqlDataReader sdr = SQLHelper.Execute(sql);
// 使用sdr
sdr.Close();
sdr = null;
===>
连接没有释放,要写上conn.Close();
Result ret = SQLHelper.Execute(sql);
// 使用ret.sdr
ret.sdr.Close();
ret.sdr = null;
ret.conn.Close();
ret.conn.Dispose();
ret.conn = null;
==>
可以这么设计,去掉ret.conn.Dispose();否则会出错
你可以参考网上别人写的sqlhelper类

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明有关C#里数据库连接释放的问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)