SqlHelper类编写前奏:DataReader关闭链接出现问题
SqlHelper是一个执行数据库操作的助手类,但是当我们没学过DataSet之前,要想使用using搭配SqlConnection和SqlCommand写出一个真正独立的SqlHelper都是不太可能的。
比如:一个常规的ExecuteReader方法如果使用上述做法,代码如下:
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 }
}
我们在窗体的按钮点击事件中使用这个类的ExecuteScalar方法获取的SqlDataReader对象
private void button1_Click(object sender, EventArgs e)
{
//使用dr变量接收ExecuteReader方法产生的SqlDataReader对象
SqlDataReader dr = libs.SqlHelper.ExecuteReader("select * from UserInfo"); MessageBox.Show(dr.HasRows.ToString());
}
执行点击事件,发现代码报异常:阅读器关闭时尝试调用 HasRows 无效
因为使用using在using的作用域结束之前会自动调用Dispose方法,导致连接关闭。而SqlDataReader对象读取的是服务器的数据,你通过ExecuteReader返回的一个SqlDataReader对象值保存了指向服务器结果集的指针并没有数据,数据还是要依赖于conn来读取的。结论:因此这里不能使用using
既然不using,自然不会报错,conn释放资源怎么办呢。于是就想到了这种办法
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 }
}
使用的时候可以这样用:
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(); }
这样就达到了释放conn链接资源的目的。
且不说这种方法多么的不规范,多么违背面向对象程序设计的思想。光说这个手动释放,有多少程序员能够准确记得这一步。
这样的做法不能使SqlHelper成为一个真正独立真正封装的类。
基于此,我们就该在SqlHelper中放弃using 和 SqlDataReader的搭配。转而使用DataSet和SqlDataAdapter方式。
DataSet就是一个离线数据集,方便管理和遍历。
因此真正的SqlHelper.cs应该是这样写的:
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; } }
}
注意:using并不是不好,他是一个很不错的资源管理工具。但是正是由于他的自动性质,在SqlHelper中产生了麻烦,故不能在SqlHelper中使用他。其他地方,比如临时定义一个sql查询,照样可以使用。而且推荐使用!
今早又想到了几点:
1.在SqlHelper并不一定都不能使用using,只是大数据查询的时候不能用,因为不能有效关闭连接。而在一些只返回某个值或者某几个值的情况下(ExecuteSalar),或者ExecuteNonQuery的情况下,可以并且推荐使用using
最新文章
- 【bzoj1076】[SCOI2008]奖励关
- tomcat架构分析 (Session管理)
- Centos6.5搭建java开发环境
- Linux内核同步机制之(二):Per-CPU变量
- Python学习笔记4(函数与模块)
- Sunscreen(POJ 3614 优先队列)
- C++标准库之queue(各函数及其使用全)
- error while loading shared libraries: libg2o_core.so: cannot open shared object file: No such file or directory解决方法
- css+jquery 实现图片局部放大预览
- Nginx 完整安装篇
- javascript 小方块平移
- [BUAA-SE-2018]结对作业测试报告
- 命令:history
- iOS 去掉UITableView风格为group时候的最顶部的空白距离
- QQ提示应用程序并行配置不正确,绿色版QQ不能运行解决方法
- ios app 开发中ipa重新签名步骤介绍
- Descriptor&;web.xml
- 《JavaScript》split和join
- 利用TLE数据确定卫星轨道(2)-SGP4模型实现
- javaweb(三十一)——国际化(i18n)
热门文章
- 1.rest之@Get和@Post请求的区别:
- @RequestMapping(value = {";list";, ";";})
- Object.fromEntries
- JVM 引用类型
- Mobius反演定理-BZOJ2154
- vue项目依赖的安装
- WLC-Virtual Interface IP
- Python socket day4
- jmeter实现对Oracle数据库的操作
- java spring-boot 服务器启动参数设置