(五)数据阅读器对象——以编程方式访问数据库
1、 创建数据阅读器对象
SqlDataReader对象只能使用SqlCommand.ExecuteReader()方法执行命令来获得,也就是说没有可以创建SqlDataReader类实例的公有构造函数。数据阅读器对象由下列任务组成:
1) 配置连接;
2) 配置一个获得行数据的命令;
3) 使用SqlCommand.ExecuteReader()方法执行该命令。
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings
[“MyConnectionString”].ConnectionString);
try
{
SqlCommand cmd = new SqlCommand ( “SELECT * FROM MyTable ”,conn );
conn.Open();
SqlDataReader reader = cmd.ExecuteReader ();
…
}
catch ( Exception ex)
{
//Handle exception
}
finally
{
conn.close();
}
2、 读取数据
获得SqlDataReader实例后,接下来就是使用该实例读取数据。可以进行下列操作:
1) 读取架构数据:
有两种方式:
每次一列:逐列获取通常更适用也更快。该方法需要用到下列方法和属性:
SqlDataReader.FieldCount : 获取数据阅读器中行数的列数;
SqlDataReader.GetName() : 获取指定列的名称(列用其int索引指定)。
SqlDataReader.GetDataTypeName() : 获取指定列的数据类型名(列用其int索引指定)。
如果知道列名,可用SqlDataReader.GetOrdinal()方法获得其索引值。
一步完成:使用SqlDataReader.GetSchemaTable()方法,它没有参数,返回DataTable实例。
2) 读取行数据:
使用Read()方法加载行。通常在while循环中调用:
While ( reader.Read() )
{
// Process row.
}
// No more rows to process.
开始循环前,可以使用SqlDataReader.HasRows 来判定结果集中是否还有行。然而,不能使用数据阅读器来判断还有多少行。如果要这样做,必须在一个独立的查询中使用聚合函数 COUNT (*),或者处理行的同时对行进行计数,然后在处理完后计算一共有多少行。
注意区别Read() 和 NextResult(),后者是移到下一个结果集中。
加载行后,需要通过提取列信息对行进行处理 。有很多方法可以将列数据提取为特定的数据类型,每种方法都以整形的列索引为参数,并返回指定类型的结果。例如,对于整形数据,可使用SqlDataReader.GetInt32 ()。也可使用SqlDataReader.GetValue(),或数据阅读器的索引器,以object引用的形式获得值。
object columnVal1 = reader.GetValue (0);
object columnVal2 = reader[0];
其重载版本为:object columnVal = reader[“MyColumn”]; 此方法比较慢,因为数据阅读器必须先获得指定列的索引值才能返回值,但其相对来说不那么重要,而使用这种方式使得代码的可读性更好。
注意,SQL类型在System.Data.SqlTypes命名空间下,只能通过GetSqlXXX()方法获得。
使用强类型方法来获得列值时,应知道在空值的情况下将发生什么。在处理值类型时,空值是不允许的。例如,当数据行中包含空值时,调用GetGuid()将导致异常。可以采用相应泊措施来处理异常,也可以使用SqlDataReader.IsDBNull()方法,它指出包含空值的列的索引。然而,如果检测到空值,可以避免使用类型化方法来获取值,因为这样会导致异常。然而,在同样的情况下, 使用GetSqlGuid()不会导致异常,而返回一个正确的SQL数据类型的实例(这里为SqlGuid)。如果试图使用这个对象的Value属性来访问它的值,将引发异常。应在使用Value属性前检查这个对象的布尔属性IsNull(这里是SqlGuid.IsNull)。最后,使用GetValue()或索引器访问数据时,空值将导致返回的结果为System.DBNull,而不会引发异常。
另一种获得行的方式是使用方法SqlDataReader.GetValue()或SqlDataReader.GetsqlValues()。二者都有一个参数,即对object数组的引用。结果是使用来自行的值来填充该数组,每个元素表示一列(按列顺序)。
遇到空值时,这些方法不会引发异常,然而,正如前面讨论的,使用这个方的SQL类型版本(GetSqlValues)获取时,如果使用Value属性来访问结果,而结果包含空值时,将引发异常。
3) 读取数据阅读器的其他属性,如实例中是否包含行,包含多少行等。
比如,FieldCount,HasRows,IsClosed判断数据库连接是否已关闭,RecordAffected指出受生成数据阅读器的命令影响的行数。
3、 数据阅读器对象的连接
数据阅读器在使用中时,其底层的SqlConnection对象不能用于其他用途。如果需要,可以通过 SqlDataReader.Connection属性访问底层连接,但唯一能执行的操作是调用连接的Close()方法关闭它。