第9章ASP.NET操作数据库通过对ADO.NET的基本讲解,以及讲解了一些数据源控件的基本用法后,本章将介绍一些ASP.NET操作数据库的高级用法,包括使用SQLHelper,以及数据源控件对数据的操作。本章是对前面的数据库知识的一种补充和提升。9.1使用ADO.NET操作数据库上一章中介绍了ADO.NET的基本概念、ADO.NET的对象,以及如何使用ADO.NET。使用ADO.NET能够极大的方便开发人员对数据库进行操作而无需关心数据库底层之间的运行,ADO.NET不仅包括多个对象,同样包括多种方法,这些方法都可以用来执行开发人员指定的SQL语句,但是这些方法实现过程又不尽相同,本节将介绍ADO.NET中数据的操作方法。9.1.1使用ExecuteReader()操作数据库使用ExecuteReader()操作数据库,ExecuteReader()方法返回的是一个SqlDataReader对象或OleDbDataReader对象。当使用DataReader对象时,不会像DataSet那样提供无连接的数据库副本,DataReader类被设计为产生只读、只进的数据流。这些数据流都是从数据库返回的。所以,每次的访问或操作只有一个记录保存在服务器的内存中。相比与DataSet而言,DataReader具有较快的访问能力,并且能够使用较少的服务器资源。DataReader对象提供了“游标”形式的读取方法,当从结果中读取了一行,则“游标”会继续读取到下一行。通过Read方法可以判断数据是否还有下一行,如果存在数据,则继续运行并返回true,否则返回false。示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';SqlConnectioncon=newSqlConnection(str);con.Open();//打开连接stringstrsql=select*frommynews;//SQL查询语句SqlCommandcmd=newSqlCommand(strsql,con);//初始化Command对象SqlDataReaderrd=cmd.ExecuteReader();//初始化DataReader对象while(rd.Read()){Response.Write(rd[title].ToString());//通过索引获取列}DataReader可以提高执行效率,有两种方式可以提高代码的性能,一种是基于序号的查询;第二种情况则是使用适当的Get方法来查询。一般来说,在数据库的设计中,需要设计索引键或主键来标识,在主键的设计中,自动增长类型是经常使用的,自动增长类型通常为整型,所以基于序号的查询可以使用DataReader,示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//设置连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接244stringstrsql=select*frommynewswhereid=1orderbyiddesc;//按标识查询SqlCommandcmd=newSqlCommand(strsql,con);//创建Command对象SqlDataReaderrd=cmd.ExecuteReader();//创建DataReader对象while(rd.Read())//遍历数据库{Response.Write(rd[title].ToString());//读取相应行的信息}当使用ExecuteReader()操作数据库时,会遇到知道某列的名称而不知道某列的号的情况,这种情况可以通过使用DataReader对象的GetOrdinal()方法获取相应的列号。此方法接收一个列名并返回此列名所在的列号,示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//创建连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接stringstrsql=select*frommynewswhereid=1orderbyiddesc;//创建执行SQL语句SqlCommandcmd=newSqlCommand(strsql,con);//创建Command对象SqlDataReaderrd=cmd.ExecuteReader();//创建DataReader对象intid=rd.GetOrdinal(title);//使用GetOrdinal方法获取title列的列号while(rd.Read())//遍历DataReader对象{Label1.Text=新闻id是+rd[id];//输出对象的值}当完成数据库操作时,需要关闭数据库连接,DataReader对象在调用Close()方法即关闭与数据库的连接,如果在没有关闭之前又打开另一个连接,系统会抛出异常。示例代码如下所示。rd.Close();//关闭DataReader对象ExecuteReader()可以执行相应的SQL语句,例如插入、更新以及删除等,当需要执行插入、更新或删除时,可以使用ExecuteReader()进行数据操作,示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//创建连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接stringstrsql=insertintomynewsvalues('执行更新后的标题');//创建执行SQL语句SqlCommandcmd=newSqlCommand(strsql,con);//创建Command对象SqlDataReaderrd=cmd.ExecuteReader();//使用ExcuteReader()方法while(rd.Read())//读取数据库{Response.Write(rd[title].ToString()+hr/);}rd.Close();//关闭DataReader对象Response.Redirect(ExecuteReader.aspx);当执行了插入、删除等数据库操作时,ExecuteReader返回为空的DataReader对象。当使用Read方法遍历读取数据库时,并不会显示相应的数据信息,因为不是查询语句,则返回一个没有任何数据的System.Data.OleDb.OleDbDataReader类型的集(EOF),但是ExecuteReader方法可以执行SQL语句。如图9-1所示。245图9-1ExecuteReader()执行查询和事务处理使用ExecuteReader()操作数据库,通常情况下是使用ExecuteReader()进行数据库查询操作,使用ExecuteReader()查询数据库能够提升查询效率,而如果需要进行数据库事务处理的话,ExecuteReader()方法并不是理想的选择。9.1.2使用ExecuteNonQuery()操作数据库使用ExecuteNonQuery()操作数据库时,ExecuteNonQuery()并不返回DataReader对象,返回的是一个整型的值,代表执行某个SQL语句后,在数据库中影响的行数,示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//创建连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接stringstrsql=selecttop5*frommynewsorderbyiddesc;SqlCommandcmd=newSqlCommand(strsql,con);//使用ExecuteNonQueryLabel1.Text=该操作影响了+cmd.ExecuteNonQuery()+行;//执行SQL语句并返回行上述代码使用了SELECT语句,并执行语句,返回受影响的行数。运行后,发现返回的结果为-1,说明,当使用SELECT语句时,并没有对任何行有任何影响。ExecuteNonQuery()通常情况下为数据库事务处理的首选,当需要执行插入、删除、更新等操作时,首选ExecuteNonQuery()。对于更新、插入和删除的SQL句,ExecuteNonQuery()方法的返回值为该命令所影响的行数。对于“CREATETABLE”和“DROPTABLE”语句,返回值为0,而对于所有其他类型的语句,返回值为-1。ExecuteNonQuery()操作数据时,可以不使用DataSet直接更改数据库中的数据,示例代码如下所示。protectedvoidButton1_Click(objectsender,EventArgse){stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//创建连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接stringstrsql=deletefrommynewswhereid4;//编写执行删除的SQL语句SqlCommandcmd=newSqlCommand(strsql,con);//创建Command对象Label1.Text=该操作影响了+cmd.ExecuteNonQuery()+行;//返回影响行数}246运行上述代码后,会执行删除id号大于4的数据事务,当执行删除并删除完毕后,则ExecuteNonQuery()方法返回受影响的行数,如图9-2所示。图9-2ExecuteNonQuery()方法ExecuteNonQuery()操作主要进行数据库操作,包括更新、插入和删除等操作,并返回相应的行数。在进行数据库事务处理时或不需要DataSet为数据库进行更新时,ExecuteNonQuery()方法是数据操作的首选。因为ExecuteNonQuery()支持多种数据库语句的执行。注意:有些项目中,通过判断ExecuteNonQuery()的返回值来判断SQL语句是否执行成功,这样是有失偏颇的,因为当使用创建表的语句时,就算执行成功也会返回-1。9.1.3使用ExecuteScalar()操作数据库ExecuteScalar()方法也用来执行SQL语句,但是ExecuteScalar()执行SQL语句后的返回值与ExecuteNonQuery()并不相同,ExecuteScalar()方法的返回值的数据类型是Object类型。如果执行的SQL语句是一个查询语句(SELECT),则返回结果是查询后的第一行的第一列,如果执行的SQL语句不是一个查询语句,则会返回一个未实例化的对象,必须通过类型转换来显示,示例代码如下所示。stringstr=server='(local)';database='mytable';uid='sa';pwd='sa';//创建连接字串SqlConnectioncon=newSqlConnection(str);//创建连接对象con.Open();//打开连接stringstrsql=select*frommynewsorderbyiddesc;SqlCommandcmd=newSqlCommand(strsql,con);Label1.Text=查询出了Id为+cmd.Execu