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

 

SqlHelper类编写前奏:DataReader关闭链接出现问题的更多相关文章

  1. Django的rest_framework的视图之Mixin类编写视图源码解析

    Mixin类编写视图 我们这里用auther表来做演示,先为auther和autherdetail写2个url url(r'^autherdetail/(?P<id>\d+)', view ...

  2. 25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有

    package zhongqiuzuoye; //自己写的方法 public class Rect { public double width; public double height; Rect( ...

  3. TCP中异常关闭链接的意义 异常关闭的情况

    终止一个连接的正常方式是发送FIN. 在发送缓冲区中 所有排队数据都已发送之后才发送FIN,正常情况下没有任何数据丢失. 但我们有时也有可能发送一个RST报文段而不是F IN来中途关闭一个连接.这称为 ...

  4. Android Java类编写规范+优化建议

    本文仅是我个人在实际开发中习惯的编写方式,当然这种方式也是来自很多官方的推荐,所以在一定程度上是可以被模仿套用的.本文将不定期更新~ 零.指导原则 优先保证可读性,不要过分追求代码艺术和效率 在可读性 ...

  5. Django的rest_framework的视图之基于通用类编写视图源码解析

    我们上一篇博客讲解了如何使用mixins类实现rest_framework的视图,但是其中有很多的冗余的代码,我们这边在来优化一下 1.queryset的视图函数 首先看下对queryset操作的视图 ...

  6. Java 从基础到进阶学习之路---类编写以及文档凝视.

    Java之前在学习过,基础知识还没有忘光,并且这些高级语言实在是太像,所以那些数据类型,或者循环控制流,以及标准设备等等就直接略过不说了. 只是一些重大概念会穿插在文章的介绍中. So,这些文章适合于 ...

  7. C++基础学习教程(七)----类编写及类的两个特性解析---&gt;多态&amp;继承

    类引入 到眼下为止我们所写的自己定义类型都是keywordstruct,从如今起我们将採用class方式定义类,这样的方式对于学习过其它高级语言包含脚本(Such as Python)的人来说再熟悉只 ...

  8. TCP四次挥手客户端关闭链接为什么要等待2倍MSL

    最长报文寿命 在TCP协议中,当发送方发送释放连接报文收到确认报文后,只是在一个方向上断开了TCP连接,然后,接收方发送释放连接的报文,发送方回复确认.此时,连接还没有释放,发送方要等待2MSL(ma ...

  9. 按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有确定位

    package com.hanqi.test; public class Rect { ; ; public double getWidth() { return width; } public vo ...

随机推荐

  1. ASP.NET + MVC5 入门完整教程三 (下) ---MVC 松耦合

    建立松耦合组件 MVC 模式最重要的特性之一视他支持关注分离,希望应用程序中的组件尽可能独立,只有很少的几个可控依赖项.在理想的情况下,每个组件都不了解其他组件,而只是通过抽象接口来处理应用程序的其他 ...

  2. oracle查询第几行到第几行的数据

    我想查询10条到20条的数据 注意: 1.大数在前,小数在后面 2.都是小于 () minus (); 运行结果:

  3. Array,String,Set,Map

    热爱前端的17号诶 积跬步以致千里 积怠惰以致深渊 博客园 首页 新随笔 联系 管理 随笔 - 58  文章 - 2  评论 - 65 最新数组方法(包括es6) for...of 是 ES6 新引入 ...

  4. Flink流处理(四)- 时间语义

    4. 时间语义(Time Semantics) 这章我们会介绍时间语义,以及在流中,对于时间的各种不同的概念的描述.同时我们也会讨论一个流处理器在事件乱序的情况下,如何能提供精准的结果,以及如何使用流 ...

  5. 题解【CJOJ1236】【复赛】指数序列求和

    P1236 - [复赛]指数序列求和 Description 求1^b+2^b+…+a^b的和除以10000的余数. Input 第一行包含一个正整数N,表示有N组测试数据接下来N行每行包含两个正整数 ...

  6. 配置SSH使用密钥认证:实现免输入密码登陆

    一.实际工作生产场景分析 张三是某公司员工,由于业务上的需求,需要经常使用SSH工具登陆服务器A的root账户进行操作,为避免重复进行密码验证身份.现采用张山的公钥发送给服务器A,免输入密码登陆到服务 ...

  7. vue $router.push 传参的问题

    $router 和 $route的区别 $route为当前router跳转对象里面可以获取name.path.query.params等 $router为VueRouter实例,想要导航到不同URL, ...

  8. HTTP状态码详解(下)

    接上文 HTTP状态码详解(上). 详细的描述状态码之(3**) 300:被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息.用户或浏览器能够自行选择一个首选的地址进 ...

  9. 实现手写体 mnist 数据集的识别任务

    实现手写体 mnist 数据集的识别任务,共分为三个模块文件,分别是描述网络结构的前向传播过程文件(mnist_forward.py). 描述网络参数优化方法的反向传播 过 程 文件 ( mnist_ ...

  10. 「题解」「BZOJ-4668」冷战

    题目 点这里 思路及代码 我们可以使用并查集的按秩合并(但是不要路径压缩). 两个集合被合并起来,连上的边的权值就设为当前时间. 然后我们可以发现,询问 \(j\) 与 \(k\) 何时联通,就是查询 ...