码迷,mamicode.com
首页 > 数据库 > 详细

SqlHelper类编写前奏:DataReader关闭链接出现问题

时间:2014-05-05 23:10:40      阅读:501      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   java   tar   

SqlHelper是一个执行数据库操作的助手类,但是当我们没学过DataSet之前,要想使用using搭配SqlConnection和SqlCommand写出一个真正独立的SqlHelper都是不太可能的。

比如:一个常规的ExecuteReader方法如果使用上述做法,代码如下:

bubuko.com,布布扣
using System.Data.SqlClient;

namespace ExecuteScalar.libs
{
    class SqlHelper
    {
        public static SqlDataReader ExecuteScalar()
        {
            //使用using管理资源
            using (SqlConnection conn = new SqlConnection("server=.;database=WebSite;uid=sa;pwd=123456"))
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select * from UserInfo";
                    conn.Open();

                    return cmd.ExecuteReader();
                }
            }
        }//end ExecuteScalar

    }
}
bubuko.com,布布扣

我们在窗体的按钮点击事件中使用这个类的ExecuteScalar方法获取的SqlDataReader对象

bubuko.com,布布扣
private void button1_Click(object sender, EventArgs e)
{
    //使用dr变量接收ExecuteReader方法产生的SqlDataReader对象
    SqlDataReader dr = libs.SqlHelper.ExecuteReader("select * from UserInfo");

    MessageBox.Show(dr.HasRows.ToString());
}
bubuko.com,布布扣

执行点击事件,发现代码报异常:阅读器关闭时尝试调用 HasRows 无效 

 

因为使用using在using的作用域结束之前会自动调用Dispose方法,导致连接关闭。而SqlDataReader对象读取的是服务器的数据,你通过ExecuteReader返回的一个SqlDataReader对象值保存了指向服务器结果集的指针并没有数据,数据还是要依赖于conn来读取的。结论:因此这里不能使用using

既然不using,自然不会报错,conn释放资源怎么办呢。于是就想到了这种办法

bubuko.com,布布扣
using System.Data.SqlClient;

namespace ExecuteScalar.libs
{
    class SqlHelper
    {
        //将conn定义为静态成员,要可以在外部手动释放掉
        public static SqlConnection conn;

        public static SqlDataReader ExecuteScalar()
        {
            //使用using管理资源
            using (conn = new SqlConnection("server=.;database=WebSite;uid=sa;pwd=123456"))
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select * from UserInfo";
                    conn.Open();

                    return cmd.ExecuteReader();
                }
            }
        }//end ExecuteScalar

    }
}
bubuko.com,布布扣

使用的时候可以这样用:

bubuko.com,布布扣
private void button1_Click(object sender, EventArgs e)
{
    //使用dr变量接收ExecuteReader方法产生的SqlDataReader对象
    SqlDataReader dr = libs.SqlHelper.ExecuteReader("select * from UserInfo");

    MessageBox.Show(dr.HasRows.ToString());
    //关闭SqlDataReader
    dr.Close();
    libs.SqlHelper.conn.Close();

}
bubuko.com,布布扣

这样就达到了释放conn链接资源的目的。

且不说这种方法多么的不规范,多么违背面向对象程序设计的思想。光说这个手动释放,有多少程序员能够准确记得这一步。

这样的做法不能使SqlHelper成为一个真正独立真正封装的类。

基于此,我们就该在SqlHelper中放弃using 和 SqlDataReader的搭配。转而使用DataSet和SqlDataAdapter方式。

DataSet就是一个离线数据集,方便管理和遍历。

因此真正的SqlHelper.cs应该是这样写的:

bubuko.com,布布扣
using System.Data.SqlClient;
using System.Data;

namespace ExecuteScalar.libs
{
    class SqlHelper
    {
        public static DataSet GetDataSet(string sql)
        {
            SqlDataAdapter sda = new SqlDataAdapter(sql,"server=.;database=WebSite;uid=sa;pwd=123456");

            DataSet dSet = new DataSet();

            sda.Fill(dSet);

            return dSet;

        }

    }
}
bubuko.com,布布扣

注意:using并不是不好,他是一个很不错的资源管理工具。但是正是由于他的自动性质,在SqlHelper中产生了麻烦,故不能在SqlHelper中使用他。其他地方,比如临时定义一个sql查询,照样可以使用。而且推荐使用!

今早又想到了几点:

  1.在SqlHelper并不一定都不能使用using,只是大数据查询的时候不能用,因为不能有效关闭连接。而在一些只返回某个值或者某几个值的情况下(ExecuteSalar),或者ExecuteNonQuery的情况下,可以并且推荐使用using

 

SqlHelper类编写前奏:DataReader关闭链接出现问题,布布扣,bubuko.com

SqlHelper类编写前奏:DataReader关闭链接出现问题

标签:style   blog   class   code   java   tar   

原文地址:http://www.cnblogs.com/hoosway/p/3704692.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!