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

NeetSonic 2016-07-23 04:39:28
如题,与数据库的连接进行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何时以及如何被释放呢,没记错的话这个叫非托管资源。
...全文
637 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
threenewbee 2016-07-24
  • 打赏
  • 举报
回复
底层ado.net是有连接池的。
threenewbee 2016-07-24
  • 打赏
  • 举报
回复
其实释放不释放都是一样的。
NeetSonic 2016-07-24
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
人是最不可靠的,包括自己。所有编程不是最重要的,工程管理才重要。最好的管理人员往往也是最好技术行家,而不是那种只懂行政手腕儿的管理者。 当你制定了合适的 SqlHelper 框架,你就不担心“连接池满”的 bug 了!
嗯,我的想法是这样的,SQLHelper的设计就是向刚才那样,只有EXcute和ExcuteNonQuery,然后在SQLHelper外在根据实际需要用到的SQL操作,再包装一个静态类SQLExcuter,这个类里面的每个查询方法都自己做好释放工作,然后只将查询结果封装到对应的类型对象之后返回。最后将SQLExcuter提供给使用者。
秋的红果实 2016-07-24
  • 打赏
  • 举报
回复
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类
xiaoqiu_net 2016-07-23
  • 打赏
  • 举报
回复
因为datareader还得读取数据,你这里返回 他就释放掉了。所以你再读数据就会异常 这里返回DataReader不要用using,using自动释放了 return sqlcom.ExecuteReader(CommandBehavior.CloseConnection); //关闭DataReader 会自动关闭Connection
  • 打赏
  • 举报
回复
人是最不可靠的,包括自己。所有编程不是最重要的,工程管理才重要。最好的管理人员往往也是最好技术行家,而不是那种只懂行政手腕儿的管理者。 当你制定了合适的 SqlHelper 框架,你就不担心“连接池满”的 bug 了!
  • 打赏
  • 举报
回复
var lst = SqlHelper.GetList<ResultType>(connstr, cmd,
        rd => new ResultType
        {
            Name = (string)rd["Name"],
            Cost = (decimal)rd["Cost"]
        });
只要将这个用来返回强类型对象的委托作为参数提供,就能返回一个强类型的对象集合。而隐藏了内部的代码。
  • 打赏
  • 举报
回复
如果你在打开 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"]
        });

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧