DataReader对象是一个读取行的只读流的方式,绑定数据时比使用数据集方式性能要高,因为它是只读的,所以如果要对数据库中的数据进行修改就需要借助其它方法将所作的更改保存到数据库。
DataReader对象不能通过直接实例化,必须借助与相关的Command对象来创建实例,例如用SqlCommand的实例的ExecuteReader()方法可以创建SqlDataReader实例。
因为DataReader对象读取数据时需要与数据库保持连接,所以在使用完DataReader对象读取完数据之后应该立即调用它的Close()方法关闭,并且还应该关闭与之相关的Connection对象。在.net类库中提供了一种方法,在关闭DataReader对象的同时自动关闭掉与之相关的Connection对象,使用这种方法是可以为ExecuteReader()方法指定一个参数,如:
SqlDataReader reader =command.ExecuteReader(CommandBehavior.CloseConnection);
CommandBehavior是一个枚举,上面使用了CommandBehavior枚举的CloseConnection值,它能在关闭SqlDataReader时关闭相应的SqlConnection对象。
并且DataReader对象读取数据有三种方式:
一种是按查询的时候列的索引用指定的方式来读取列值,无需做相应转换,如GetByte(int i)就是读取第i列的值并且转换成byte类型的值。第这种方法的优点是指定列后直接将该列的直接读取出来了,无需再转换,缺点是一旦指定的列不能按照指定的方式转换时就会抛出异常,比如数据库里字段的类型是string类型或者该字段的值为空时按照GetByte(i)这种方式读取会抛出异常。
第二种方式就是按照列索引的方式读取,在读取的时候并不进行值转换,如:reader[5]就是读取第5列的值(这里reader是一个Reader对象的实例),这样得到的值是一个object类型的值,这也很好理解,因为在数据库可能存储各种类型的值,而object是所有类的基类,所以这个方法不会抛出异常。如果要得到它的正确类型,还需要根据数据库里的字段进行进行相应转换。
最后一种是按照列名的方式去读,并且在读的时候也不进行相应转换,得到的是object类型的值。
综合前面三种方式各有特点,第一种方式最直接,但是有可能抛出异常,第二种方式比第一种稍微灵活一些,我们可以根据读取到值为空(在.net里用DBNull类来表示,可以表示数据库中任意数据类型的空值),我们就不进行相应的类型转换,避免出现异常。第三种方式按照列的名字来读取数据,也需要按照第二种方式进行一定的转换。就性能来说第一种最高,第二种稍低,第三种最低(这很好理解,假设要在一个旅馆里找人直通过房间号找肯定比通过名字找快),就灵活性来说第三种最灵活,第二种次之,第一种最不灵活(假如在后来编写SQL语句中更改了列的索引,第一种和第二种都可能出现问题)。实际开发中根据实际情况选择合适的方式。
下面是一个使用DataReader对象读取数据的例子,因为代码不是很多并且也不复杂,所以采用了单页模式,并且还演示了三种读取数据的方式,代码如下:
01.<%@ Page Language="C#" %>
02.<%@ Import Namespace="System.Data.SqlClient" %>
03.<%@ Import Namespace="System.Data" %>
04.<%@ Import Namespace="System.Text" %>
05.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "" >
42.<head runat="server">
43. <title>无标题页</title>
44.</head>
45.<body>
46. <form id="form1" runat="server">
47. <div>
48. <table border="1" cellpadding="0" cellspacing="0">
49. <tr><td>编号</td><td>帐号</td><td>真实姓名</td><td>年龄</td><td>性别</td><td>手机</td><td>电话</td><td>电子邮件</td></tr>
50. <%
51. //在页面中调用后台代码,这样也能保证生成的代码不会位于<html></html>标记之外
52. ShowData();
53. %>
54. </table>
55. </div>
56. </form>
57.</body>
58.</html>
下面是运行结果: