第9章 ASP.NET操作数据库

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。示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";

            SqlConnection con = new SqlConnection(str);

            con.Open();                                                                                               //打开连接

            string strsql = "select * from mynews";                                                        //SQL查询语句

            SqlCommand cmd = new SqlCommand(strsql, con);                    //初始化Command对象

            SqlDataReader rd = cmd.ExecuteReader();                                      //初始化DataReader对象

            while (rd.Read())

            {

                Response.Write(rd["title"].ToString());                                         //通过索引获取列

            }

DataReader可以提高执行效率,有两种方式可以提高代码的性能,一种是基于序号的查询;第二种情况则是使用适当的Get方法来查询。一般来说,在数据库的设计中,需要设计索引键或主键来标识,在主键的设计中,自动增长类型是经常使用的,自动增长类型通常为整型,所以基于序号的查询可以使用DataReader,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //设置连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select * from mynews where id=1 order by id desc";     //按标识查询

            SqlCommand cmd = new SqlCommand(strsql, con);                             //创建Command对象

            SqlDataReader rd = cmd.ExecuteReader();                                               //创建DataReader对象

            while (rd.Read())                                                                                               //遍历数据库

            {

                Response.Write(rd["title"].ToString());                                                  //读取相应行的信息

            }

当使用ExecuteReader()操作数据库时,会遇到知道某列的名称而不知道某列的号的情况,这种情况可以通过使用DataReader对象的GetOrdinal()方法获取相应的列号。此方法接收一个列名并返回此列名所在的列号,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select * from mynews where id=1 order by id desc";     //创建执行SQL语句

            SqlCommand cmd = new SqlCommand(strsql, con);                             //创建Command对象

            SqlDataReader rd = cmd.ExecuteReader();                                               //创建DataReader对象

            int id = rd.GetOrdinal("title");                                               //使用GetOrdinal方法获取title列的列号

            while (rd.Read())                                                                                               //遍历DataReader对象

            {

                Label1.Text = "新闻id" + rd["id"];                                                       //输出对象的值

            }

当完成数据库操作时,需要关闭数据库连接,DataReader对象在调用Close()方法即关闭与数据库的连接,如果在没有关闭之前又打开另一个连接,系统会抛出异常。示例代码如下所示。

            rd.Close();                                                                                                          //关闭DataReader对象

ExecuteReader()可以执行相应的SQL语句,例如插入、更新以及删除等,当需要执行插入、更新或删除时,可以使用ExecuteReader()进行数据操作,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "insert into mynews values ('执行更新后的标题')";           //创建执行SQL语句

            SqlCommand cmd = new SqlCommand(strsql, con);                             //创建Command对象

            SqlDataReader rd = 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所示。

 

9-1  ExecuteReader()执行查询和事务处理

使用ExecuteReader()操作数据库,通常情况下是使用ExecuteReader()进行数据库查询操作,使用ExecuteReader()查询数据库能够提升查询效率,而如果需要进行数据库事务处理的话,ExecuteReader()方法并不是理想的选择。

9.1.2  使用ExecuteNonQuery()操作数据库

使用ExecuteNonQuery()操作数据库时,ExecuteNonQuery()并不返回DataReader对象,返回的是一个整型的值,代表执行某个SQL语句后,在数据库中影响的行数,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select top 5 * from mynews order by id desc";

            SqlCommand cmd = new SqlCommand(strsql, con);                             //使用ExecuteNonQuery

            Label1.Text="该操作影响了"+cmd.ExecuteNonQuery()+"";                   //执行SQL语句并返回行

上述代码使用了SELECT语句,并执行语句,返回受影响的行数。运行后,发现返回的结果为-1,说明,当使用SELECT语句时,并没有对任何行有任何影响。ExecuteNonQuery()通常情况下为数据库事务处理的首选,当需要执行插入、删除、更新等操作时,首选ExecuteNonQuery()

对于更新、插入和删除的SQL句,ExecuteNonQuery()方法的返回值为该命令所影响的行数。对于“CREATE TABLE”和“DROP TABLE”语句,返回值为0,而对于所有其他类型的语句,返回值为-1ExecuteNonQuery()操作数据时,可以不使用DataSet直接更改数据库中的数据,示例代码如下所示。

        protected void Button1_Click(object sender, EventArgs e)

        {

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "delete from mynews where id>4";                                               //编写执行删除的SQL语句

            SqlCommand cmd = new SqlCommand(strsql, con);                             //创建Command对象

            Label1.Text = "该操作影响了" + cmd.ExecuteNonQuery() + "";             //返回影响行数

        }

运行上述代码后,会执行删除id号大于4的数据事务,当执行删除并删除完毕后,则ExecuteNonQuery()方法返回受影响的行数,如图9-2所示。

 

9-2  ExecuteNonQuery()方法

ExecuteNonQuery()操作主要进行数据库操作,包括更新、插入和删除等操作,并返回相应的行数。在进行数据库事务处理时或不需要DataSet为数据库进行更新时,ExecuteNonQuery()方法是数据操作的首选。因为ExecuteNonQuery()支持多种数据库语句的执行。

注意:有些项目中,通过判断ExecuteNonQuery()的返回值来判断SQL语句是否执行成功,这样是有失偏颇的,因为当使用创建表的语句时,就算执行成功也会返回-1

9.1.3  使用ExecuteScalar()操作数据库

ExecuteScalar()方法也用来执行SQL语句,但是ExecuteScalar()执行SQL语句后的返回值与ExecuteNonQuery()并不相同,ExecuteScalar()方法的返回值的数据类型是Object类型。如果执行的SQL语句是一个查询语句(SELECT),则返回结果是查询后的第一行的第一列,如果执行的SQL语句不是一个查询语句,则会返回一个未实例化的对象,必须通过类型转换来显示,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select * from mynews order by id desc";

            SqlCommand cmd = new SqlCommand(strsql, con);

            Label1.Text = "查询出了Id" + cmd.ExecuteScalar() /;                           //使用ExecuteScalar查询

通常情况下ExecuteNonQuery()操作后返回的是一个值,而ExecuteScalar()操作后则会返回一个对象,ExecuteScalar()经常使用于当需要返回单一值时的情况。例如当插入一条数据信息时,常常需要马上知道刚才插入的值,则可以使用ExecuteScalar()方法。示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "insert into mynews values ('刚刚插入的id是多少?')

            SELECT  @@IDENTITY  as  'bh'";                                                           //插入语句

            SqlCommand cmd = new SqlCommand(strsql, con);                             //执行语句

            Label1.Text = "刚刚插入的行的id" + cmd.ExecuteScalar();                 //返回赋值

上述代码使用了SELECT  @@IDENTITY语法获取刚刚执行更新后的id值,然后通过使用ExecuteScalar()方法来获取刚刚更新后第一行第一列的值。

9.1.4  使用ExecuteXmlReader()操作数据库

ExecuteXmlReader()方法用于操作XML数据库,并返回一个XmlReader对象,若需要使用ExecuteXmlReader()方法,则必须添加引用System.XmlXmlReader类似于DataReader,都需要通过Command对象的ExecuteXmlReader()方法来创建XmlReader的对象并初始化,示例代码如下所示。

            XmlReader xdr = cmd.ExecuteXmlReader();                                                                 //创建XmlReader对象

ExecuteXmlReader()返回XmlReader对象,XmlReader特性如下所示:

q      XMLReader是面向流的,它把XML文档看作是文本数据流。

q      XMLReader是一个抽象类。

q      XMLReader使用pull模式处理流。

q      三个派生类:XMLTextReaderXMLNodeReaderXMLValidatingReader

下面代码实现了获取当前节点中属性的个数。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select * from mynews order by id desc FOR XML AUTO, XMLDATA";

            SqlCommand cmd = new SqlCommand(strsql, con);                             //创建Command对象

            XmlReader xdr = cmd.ExecuteXmlReader();                                                        //创建XmlReader对象

            Response.Write(xdr.AttributeCount);                                                            //读取节点个数

上述代码使用了SQL语言中的FOR XML AUTO,XMLDATA关键字,当执行ExecuteXmlReader()方法时,会返回XmlReader对象,若不指定FOR XML AUTO,XMLDATA关键字,则系统会抛出异常。

9.2  ASP.NET创建和插入记录

在数据库操作中,经常需要对数据库中的内容进行插入操作。例如当有一个用户发布了评论,或者一个用户要购买某个商品,都需要插入记录来保存用户的相应的信息,以便当用户再次登录网站或应用时,能够及时获取自己购买的信息。

9.2.1  SQL INSERT数据插入语句

使用SQL INSERT语句能够实现数据库的插入,SQL语句必须遵照一些规范,SQL INSERT语句的一般语法形式如下所示:

    INSERT [INTO]

    {table_name}

    {

     [(column_list)]

     {

     VALUES({DEFAULT|NULL|expression} [,…n])

    }

    }

上述代码规范了INSERT语句的编写规范,其中:

q      INSERTSQL插入关键字。

q      [INTO]是表名称之前能够包含的可选关键字。

q      Table_name是相关的表名称。

q      column_list是列的集合,如果有多个列可用都好隔开。

q      VALUES是相应的列的值。

如果需要向表mytables插入数据,而mytables里包括自动增长的主键idtitle两列,则INSERT语句可以编写为如下代码。

    INSERT INTO mytables VALUES (‘新的新闻标题’)

上述代码向表mytables中插入了一条新记录,并将title赋值为“新的新闻标题”。值得注意的是,在这条语句中,并没有编写列的集合,是因为当不编写column_list时,则默认为每一个列插入数值。

注意:自动增长的主键类型的字段,无需向数据中插入数值,因为SQL Server会自动为该列赋值。

如果需要当插入数据时,需要指定插入相应的列的值,则可以将SQL语句代码编写如下。

    INSERT INTO mytables (title) VALUES (‘新的新闻标题’)

上述代码指定了列title,并对应了相应的值。若在表中存在多个列,列的顺序和列相应的值的顺序必须匹配。例如有3列并分别为number1string2datetime3,当需要向其中插入数据时,则可以编写以下SQL语句。

    INSERT INTO examtable (number1,string2,datetime3) VALUES (1,’this is a string’,’2008/9/18’)

上述代码编写了INSERT语句以便数据的插入,同样在插入语句中如果需要插入所有的列,可以简化INSERT语句以便快速进行数据插入,示例代码如下所示。

    INSERT INTO examtable VALUES (1,’this is a string’,’2008/9/18’)

值得注意的是,无论按照何种方法编写SQL语句,值和列都应该相互匹配。

9.2.2  使用Command对象更新记录

编写了SQL语句后,必须执行SQL语句,在ADO.NET中,执行SQL语句有很多方法,其中推荐使用Command命令的ExecuteNonQuery()。执行SQL语句的命令的必要步骤如下所示。

q      打开数据连接。

q      创建一个新的Command对象。

q      定义一个SQL命令。

q      执行SQL命令。

q      关闭连接。

从上面的步骤可以发现执行SQL语句是非常容易的,首先必须要打开到数据库的连接,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";

            SqlConnection con = new SqlConnection(str);                                 //创建连接对象

            con.Open();                                                                                               //打开连接

其中,str是数据连接字串,用来初始化Connection对象,说明如何连接数据库,当数据库连接完毕后,可以使用Open方法打开数据连接。完成数据库连接后,需创建一个新的Command对象,示例代码如下所示。

            SqlCommand cmd = new SqlCommand("insert into mynews value ('插入一条新数据')", con);

Command对象的构造函数的参数有两个,一个是需要执行的SQL语句,令一个是数据库连接对象。创建Command对象后,就可以执行SQL命令,执行后完成并关闭数据连接,示例代码如下所示。

            cmd.ExecuteNonQuery();                                                                       //执行SQL命令

            con.Close();                                                                                                       //关闭连接

上述代码使用了ExecuteNonQuery()方法执行了SELECT语句的操作,当执行完毕后就需要对现有的连接进行关闭,以释放系统资源。

9.2.3  使用DataSet数据集插入记录

使用INSERT语句能够完成数据插入,使用DataSet对象也可以完成数据插入。为了将数据库的数据填充到DataSet中,则必须先使用DataAdapter对象的方法实现填充,当数据填充完成后,开发人员可以将记录添加到DataSet对象中,然后使用Update方法将记录插入数据库中。使用DataSet更新记录的步骤如下所示:

q      创建一个Connection对象。

q      创建一个DataAdapter对象。

q      初始化适配器。

q      使用数据适配器的Fill方法执行SELECT命令,并填充DataSet

q      使用DataTable对象提供的NewRow方法创建新行。

q      将数据行的字段设置为插入的值。

q      使用DataRowAdd类的Add方法将数据行添加到数据表中。

q      DataAdapter类的InsertCommand属性设置成需要插入记录的INSERT语句。

q      使用数据适配器提供的Update方法将新记录插入数据库。

q      使用DataSet类提供的AcceptChanges方法将数据库与内存中的数据保持一致。

当使用DataSet插入记录前,需要创建Connection对象以保证数据库连接,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";                         //创建连接字串

            SqlConnection con = new SqlConnection(str);                                                             //创建连接对象

            con.Open();                                                                                                                           //打开连接

上述代码创建了一个数据库连接,并打开了数据库连接。完成数据连接后,就需要查询表中的数据并使用DataAdapter对象初始化适配器,示例代码如下所示。

            string strsql = "select * from mynews";                                                                                    //编写SQL语句

            SqlDataAdapter da = new SqlDataAdapter(strsql, con);                                                       //创建适配器

DataAdapter对象默认构造函数包括两个参数,其中一个参数是需要执行的SQL语句,另一个是Connection对象。在初始化适配器后,需要对适配器的相应的属性做设置,使用SqlCommandBuilder对象可以让系统构造InsertCommand属性,示例代码如下所示。

            SqlCommandBuilder build = new SqlCommandBuilder(da);                                             //构造SQL语句

使用适配器的Fill方法能够填充DataSet数据集,示例代码如下所示。

            DataSet ds = new DataSet();                                                                                            //创建数据集

            da.Fill(ds, "datatable");                                                                                                                //填充数据集

            DataTable tb = ds.Tables["datatable"];                                                                           //创建表

            tb.PrimaryKey = new DataColumn[] { tb.Columns["id"] };                                             //创建表的主键

上述代码创建了一个DataSet数据集对象,被填充数据后,数据集中表的名称被命名为datatable,该命名与数据库中的表的名称并不冲突。填充了DataSet数据对象后,需要使用DataRow对象为DataSet添加数据,示例代码如下所示。

            DataRow row = ds.Tables["datatable"].NewRow();                                                      //创建DataRow

            row["title"] = "使用DataSet插入新行";                                                                              //赋值新列

            row["id"] = "15";

上述代码使用了NewRow方法创建新行返回DataRow对象,当DataRow对象中的相应的元素被赋值后,则需要使用Rows.Add方法增加新行,因为只对DataRow对象赋值,并不能自动的在数据库中增加新行。示例代码如下所示。

            ds.Tables["datatable"].Rows.Add(row);                                                                                   //添加新行

上述代码将数据更新到DataSet数据集中,为了保持数据集中的数据和数据库的数据的一致性,需使用Update方法,示例代码如下所示。

            da.Update(ds, "datatable");                                                                                               //更新数据

当执行了Update方法后,数据库中的数据就会同步DataSet数据集中的数据进行数据更新。

9.3  ASP.NET更新数据库

在应用程序的开发中,常常会需要对数据库中现有的内容进行更新操作。ADO.NET提供了若干不同的更新数据库中记录的方法,如果需要更新数据库中的某列的值或者某几列的值,则需要使用SQL UPDATE命令进行数据库更新。

9.3.1  SQL UPDATE数据更新语句

使用SQL UPDATE语句能够实现数据库中数据的更新,SQL UPDATE语句的一般语法格式如下所示。

    UPDATE

    {table_name}

    {

     SET column1_name=expression1,

         column2_name=expression2,

         .

         .

         columnN_name=expressionN

    {WHERE condition1 AND|OR condition2}

    }

上述代码规范了UPDATE语句的编写规范,其中:

q      UPDATESQL更新关键字。

q      table_name是需要更新的表的名称。

q      columnN_name是需要更新的列的名称。

q      expression是列相应的值。

q      WHERESQL语句关键字。

q      condition是条件。

如果需要更新表mytable中的某行的数据,则可以编写SQL UPDATE语句进行更新,示例代码如下所示。

    UPDATE mytable SET title=’修改后的数据’ where id=3

上述代码更新了id3的数据中的title,并将title字段的值修改为“修改后的数据”。

9.3.2  使用Command对象更新记录

如需要执行UPDATE语句时,同样可以使用Command对象执行语句。Command对象基本上能够执行所有需要进行数据更新的SQL语句。使用Command对象进行数据库操作的步骤基本如下所示。

q      创建数据库连接。

q      创建一个Command对象,并指定一个SQL UPDATE(或存储过程)。

q      使用Command对象的ExecuteNonQuery()方法执行UPDATE(或存储过程)。

q      关闭数据库连接。

当需要执行UPDATE语句时,首先必须要打开到数据库的连接,打开连接后,使用Command对象执行SQL语句,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";

            SqlConnection con = new SqlConnection(str);                                 //创建连接对象

            con.Open();                                                                                               //打开连接

其中,str同样是数据连接字串,用来初始化Connection对象,说明如何连接数据库,当数据库连接完毕后,可以使用Open方法打开数据连接。完成数据库连接后,需创建一个新的Command对象进行数据更新,示例代码如下所示。

            SqlCommand cmd = new SqlCommand("UPDATE mynews SET title=’修改后的数据

            where id=3", con);                                                                                   //创建Command对象

Command对象的构造函数的参数有两个,一个是需要执行的SQL语句,令一个是数据库连接对象。创建Command对象后,就可以执行SQL命令,执行后完成并关闭数据连接,示例代码如下所示。

            cmd.ExecuteNonQuery();                                                                       //执行SQL命令

            con.Close();                                                                                                       //关闭连接

上述代码使用了ExecuteNonQuery()方法进行SQL UPDATE语句的执行,从而能够更新数据库中的相应数据。

9.3.3  使用DataSet数据集更新记录

ADO.NETDataSet对象提供了更好的编程实现数据库的更新功能。因为DataSet对象与数据库始终不是连接的,开发人员可以向脱离数据库的DataSet对象中增加列、删除列或更新列。当完成了修改后,则可以通过将DataSet对象连接到DataAdapter对象来将记录传输给数据库。DataSet更新记录的步骤如下所示。

q      创建一个Connection对象。

q      创建一个DataAdapter对象。

q      初始化适配器。

q      使用数据适配器的Fill方法执行SELECT命令,并填充DataSet

q      执行SqlCommandBuilder方法生成UpdataCommand方法。

q      创建DataTable对象并指定相应的DataSet中的表。

q      创建DataRow对象并查找需要修改的相应行。

q      更改DataRow对象中的列的值。

q      使用Update方法进行数据更新。

在更新记录前,首先需要查询出相应的数据,查询相应的数据后才能够填充DataSet,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";       //创建连接字串

            SqlConnection con = new SqlConnection(str);                                          //创建连接对象

            con.Open();                                                                                                        //打开连接

            string strsql = "select * from mynews";                                                                  //执行查询

            SqlDataAdapter da = new SqlDataAdapter(strsql, con);                                    //使用DataAdapter

            DataSet ds = new DataSet();                                                                          //使用DataSet

            da.Fill(ds, "datatable");                                                                                              //使用Fill方法填充DataSet

上述代码将查询出来的数据集保存在表为datatableDataSet记录集中,DataSet记录集的表的名称可以按照开发人员的喜好来编写,从而区分内存中表的数据和真实的数据库的区别。当需要处理数据时,只需要处理相应名称的表即可,示例代码如下所示。

            DataTable tb = ds.Tables["datatable"];

当需要执行更新时,可直接使用DataSet对象进行更新操作来修改其中的一行或多行记录,示例代码如下所示。

            DataTable tb = ds.Tables["datatable"];

            tb.PrimaryKey = new DataColumn[] { tb.Columns["id"] };

            DataRow row = tb.Rows.Find(1);

            row["title"] = "新标题";

当需要更新某个记录时,必须在更新之前查找到该行的记录。可以使用Rows.Find方法查找到相应的行,然后将数据集表中的该行的列值进行更新。使用DataAdapterUpdate方法可以更新DataSet数据集,并保持数据集和数据库中数据的一致性,示例代码如下所示。

            da.Update(ds, "datatable");

在执行以上代码,可能会抛出异常“当传递具有已修改行的DataRow集合时,更新要求有效的UpdateCommand”。这是因为在更新时,并没有为DataAdapter对象配置UpdateCommand方法,可以通过SqlCommandBuilder对象配置UpdateCommand方法,示例代码如下所示。

            SqlCommandBuilder build = new SqlCommandBuilder(da);

上述代码为DataAdapter对象自动配置了UpdateCommandDeleteCommand等方法,当执行更新时,无需手动配置UpdateCommand方法。

9.4  ASP.NET删除数据

当数据库中的数据过多,或需要对数据库进行数据优化时,则可能需要对数据库中的数据进行删除,例如用户的操作,长期不上线的用户资料,都可以删除。ADO.NET提供多种数据库的删除方法,并且同样支持DataSet方法删除数据库。

9.4.1  SQL DELETE数据删除语句

使用SQL DELETE语句能够实现数据库中数据的更新,SQL DELETE语句的一般语法格式如下所示。

DELETE [FROM]

{table_name}

[WHERE condition1 AND|OR condition2]

上述代码规范了DELETE语句的编写规范,其中:

q      DELETESQL删除关键字。

q      FORM是一个可以选择的关键字。

q      table_name是表的名称。

q      WHERE是一个SQL关键字。

q      conditionN是执行DELETE命令中需要达成的若干条件。

SQL DELETE相对来说比较简单,当需要对某个表中的数据进行删除时,可以使用DELETE语句来执行删除操作,在编写DELETE语句时,需要指定表,并且指定相应的条件,示例代码如下所示。

DELETE FROM mynews WHERE ID=3

上述代码指定删除了mynews表中ID3的行。如果不编写WHERE子句,则该表中所有的行都能够达成删除的条件,则会删除表中所有的行,示例代码如下所示。

DELETE FROM mynews

在编写删除语句时,可以通过编写相应的条件来提高执行的效率。

9.4.2  使用Command对象删除记录

当需要执行删除语句,可以使用Command对象来删除数据库中的记录。Command对象的使用方法在前面的SQL语句介绍中已经讲的比较多了,在删除记录时,其使用方法基本相同。使用Command对象进行数据库操作的步骤基本如下所示。

q      创建数据库连接。

q      创建一个Command对象,并指定一个SQL DELETE(或存储过程)。

q      使用Command对象的ExecuteNonQuery()方法执行DELETE(或存储过程)。

q      关闭数据库连接。

当需要执行DELETE语句时,首先必须要打开到数据库的连接,打开连接后,使用Command对象执行SQL语句,示例代码如下所示。

            string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";

            SqlConnection con = new SqlConnection(str);

            con.Open();                                                                                               //打开连接

完成数据库连接后,需创建一个新的Command对象,示例代码如下所示。

            SqlCommand cmd = new SqlCommand("Delete mynews where id=3", con);

Command对象的构造函数的参数有两个,一个是需要执行的SQL语句,令一个是数据库连接对象。

创建Command对象后,就可以执行SQL命令,执行后完成并关闭数据连接,示例代码如下所示。

            cmd.ExecuteNonQuery();                                                                       //执行SQL命令

            con.Close();                                                                                                       //关闭连接

9.4.3  使用DataSet数据集删除记录

使用DataSet删除记录和使用DataSet更新记录非常的相似,DataSet删除记录的步骤如下所示。

q      创建一个Connection对象。

q      创建一个DataAdapter对象。

q      初始化适配器。

q      使用数据适配器的Fill方法执行SELECT命令,并填充DataSet

q      执行SqlCommandBuilder方法生成UpdataCommand方法。

q      创建DataTable对象并指定相应的DataSet中的表。

q      创建DataRow对象并查找需要修改的相应行。

q      使用Delete方法删除该行。

q      使用Updata方法进行数据更新。

在删除记录前,首先需要创建连接,示例代码如下所示。

           string str = "server='(local)';database='mytable';uid='sa';pwd='sa'";

            SqlConnection con = new SqlConnection(str);

            con.Open();

            string strsql = "select * from mynews";

上述代码创建了与数据库的连接,并编写SQL查询语句来填充DataSet。填充DataSet对象需使用DataAdapter,示例代码如下所示。

            SqlDataAdapter da = new SqlDataAdapter(strsql, con);

            SqlCommandBuilder build = new SqlCommandBuilder(da);

            DataSet ds = new DataSet();

            da.Fill(ds, "datatable");

编写完成后,需要创建DataTable对象对DataSet中相应的数据进行操作,其代码和更新记录基本相同,示例代码如下所示。

            DataTable tb = ds.Tables["datatable"];

            tb.PrimaryKey = new DataColumn[] { tb.Columns["id"] };

            DataRow row = tb.Rows.Find(3);

在进行删除之前,同样需要找到相应的行,来指定删除语句所需要删除的行,示例代码如下所示。

            row.Delete();

读者可以看到,DataSet删除方法与更新方法不同的地方只操作语句的不同,在更新中使用的是Update()方法,而在删除中使用的是Delete()方法。

注意:当使用Delete方法删除记录行的时候,可以通过调用DataRow对象的RejectChanges方法取消对记录的删除,当使用该方法删除记录行时,该行的状态会恢复为Unchanged

在删除完毕后,同样需要保持DataSet中的数据和数据库中的数据的一致性,示例代码如下所示。

            da.Update(ds, "datatable");

使用Update方法能够使DataSet中的数据和数据库中的数据保持一致性,在ASP中,这种方法也比较常见。

9.5  使用存储过程

存储过程在开发过程中经常被使用,因为存储过程能够将数据操作和程序操作在代码上分离,而且存储过程相对于SQL语句而言,具有更好的性能和安全性,使用存储过程能够提高应用程序的性能和安全性。

9.5.1  存储过程的优点

在数据库操作中,已经有了SQL语句,为何还需要存储过程。因为存储过程有SQL语句不能具备的特点和优点,以至于存储过程能在严格的数据库驱动的应用程序中起到重要的作用。存储和过程有点包括:

q      事务处理。

q      速度和性能。

q      过程控制。

q      安全性。

q      减少网络流量和通信。

q      模块化。

1.事务处理

存储过程中,包括多个SQL语句,存储过程中的SQL语句属于事务处理的范畴。也就是说,存储过程类似于一个函数,当执行存储过程时,存储过程中的SQL语句要不都执行,要不都不执行。

2.速度和性能

存储过程由数据库服务器编译和优化,优化包括使用存储过程在运行时所必须的特定数据库的结构信息,这样在执行过程中会节约很多时间。存储过程完全在数据库服务器上执行,避免了大量的SQL语句代码的传递,对于循环使用SQL语句而言,存储过程在速度和性能上都被优化。

3.过程控制

在编写存储过程中,可以使用IF ELSEFOR以及WHILE循环,这些语句并不能在SQL语句中编写,但是可以在存储过程中编写。当需要进行大量的和复杂的操作时,SQL语句需要通过和编程语言一同编写才能实现,而且实现复杂。相比之下,存储过程可以对过程进行控制。

4.安全性

存储过程也可以作为额外的安全层。开发人员或者用户,都只能对数据库中的存储过程进行使用,而无法直接对表进行数据操作,这样封装了数据操作,提高安全性。

5.减少网络流量和通信

存储过程是在数据库服务器上运行的,在使用存储过程中,无需将大量的SQL语句代码传递给数据库服务器,而只需告诉数据库服务器执行哪个存储过程即可,而数据库服务器则会自行执行中间处理操作,而不会通过网络传递不必要的数据。

6.模块化

正如代码编写规范和设计模式一样,通常情况下,开发团队或者公司需要严谨的代码编写风格和良好的协调能力,例如一个团队有人专门负责编码,有人专门负责数据库开发,那么可以让数据库开发人员负责数据库的开发,而编码的程序员只需要使用数据库开发人员设计的存储过程即可。在这种情况下,数据库操作和应用程序编码的操作被分开,在维护、管理中,也非常方便,如果数据库存储过程的代码出现问题,则只需要修改存储过程中的代码即可。

9.5.2  创建存储过程

存储过程可以通过SQL Server Management Studio创建,也可以使用.NET框架通过编程实现.SQL Server Management Studio创建存储过程比较方便,右击【对象资源管理器】中的相应的数据库,在下拉菜单中选择【可编程性】选项并选择【存储过程】选项。单击右键,选择【新建存储过程】选项,系统会自动创建一个新的标签(tab)窗口,以提供输入存储过程语句,如图9-3所示。

 

9-3  使用Server Management Studio创建存储过程

tab窗口中输入存储过程,代码如下所示。

    CREATE PROC myproc

    (

    @id int,

    @title varchar(50) OUTPUT

    )

    AS

    SET NOCOUNT ON

    DECLARE @newscount int

    SELECT @title=mynews.title,@newscount=COUNT(mynews.id)

    FROM mynews

    WHERE (id=@id)

    GROUP BY mynews.title

    RETURN @newscount

上述存储过程返回了数据库中新闻的标题内容。“@id”表示新闻的id@title表示新闻的标题,此存储过程将返回“@title”的值,并且返回新闻的总数。在C#中同样可以使用编程实现存储过程的创建,示例代码如下所示。

                string str = "CREATE PROC myproc" +

                "(" +

                "@id int," +

                "@title varchar(50) OUTPUT" +

                ")" +

                "AS" +

                "SET NOCOUNT ON" +

                "DECLARE @newscount int" +

                "SELECT @title=mynews.title,@newscount=COUNT(mynews.id)" +

                "FROM mynews" +

                "WHERE (id=@id)" +

                "GROUP BY mynews.title" +

                "RETURN @newscount";

                SqlCommand cmd = new SqlCommand(str, con);

                cmd.ExecuteNonQuery();                         //使用cmdExecuteNonQuery方法创建存储过程

上述代码通过使用SqlCommand对象的ExecuteNonQuery()方法在数据库中创建了一个存储过程,该存储过程用于返回了数据库中新闻的标题内容。

9.5.3  调用存储过程

创建存储过程之后,可以在.NET应用程序中使用存储过程。存储过程可以看成是一个函数,可以对存储过程进行调用,传递参数,接受返回值。在调用存储过程前,首先要与数据库建立连接,示例代码如如下所示。

                string str = "server='(local)';database='mytable';uid='sa';pwd='Sa'";

                SqlConnection con = new SqlConnection(str);

                con.Open();                                                                                                //打开连接

建立与数据库连接后,需要使用Command对象使用存储过程,Command对象接受的两个参数分别为SQL语句和Connection对象,在使用存储过程时,其中表示SQL语句的参数可以直接编写为存储过程名,代码如下所示。

                SqlCommand cmd = new SqlCommand("getdetail", con);             //使用存储过程

默认情况下,Command对象的类型是SQL语句,必须将Command对象的CommandType属性设置为存储过程,系统才会调用存储过程,示例代码如下所示。

                cmd.CommandType = CommandType.StoredProcedure;              //设置Command对象的类型

设置执行类型后,需要为存储过程增加参数,示例代码如下所示。

                SqlParameter spr;                                                                                             //表示执行一个存储过程

                spr = cmd.Parameters.Add("@id", SqlDbType.Int);                                     //增加参数id

                spr = cmd.Parameters.Add("@title", SqlDbType.NChar,50);           //增加参数title

                spr.Direction = ParameterDirection.Output;                                        //该参数是输出参数

                spr = cmd.Parameters.Add("@count", SqlDbType.Int);                     //增加count参数

                spr.Direction = ParameterDirection.ReturnValue;                             //该参数是返回值

                cmd.Parameters["@id"].Value = 1;                                                                 //为参数初始化

                cmd.Parameters["@title"].Value = null;                                                //为参数初始化

参数设置完毕后,执行ExecuteNonQuery方法能够执行存储过程,就相当于开始调用函数,示例代码如下所示。

                cmd.ExecuteNonQuery();                                                                        //执行存储过程

当存储过程执行完毕后,能够获取参数和返回值,示例代码如下所示。

                Label1.Text = cmd.Parameters["@count"].Value.ToString();           //获取返回值

使用SQL Server Management Studio同样能够执行存储过程,单击存储过程,单击右键,选择执行存储过程,系统会提示输入参数,如图9-4所示。输入相应的参数,单击确定,系统会执行存储过程并返回相应的值,如图9-5所示。

  

9-4  为存储过程传递参数                         9-5  执行完成

使用SQL Server Management Studio能够快速的创建和使用存储过程,同样,能够通过编程的方法实现存储过程的创建、参数的传递以及执行。存储过程的优点就在于速度比较快,能够控制过程、减少网络通信和模块化,熟练的使用存储过程能够提高应用程序的性能和复用性。

9.6  ASP.NET数据库操作实例

在了解了数据源控件和数据绑定控件的功能和使用方法,并且了解了ADO.NET的基本知识后,就可以使用控件和ADO.NET来操作数据库。ASP.NET提供了强大的数据源控件和数据绑定控件,能够迅速的对数据库进行操作,同时,使用ADO.NET对数据进行操作,能够加深对ADO.NET的认识。

9.6.1  制作用户界面(UI

使用数据控件和数据源控件显式数据,则需要为控件制作相应的用户界面,让数据控件对用户呈现的效果更好。首先,需要使用创建数据绑定控件GridView和数据源控件,并配置数据源控件,如图9-6所示。

显然,对于用户而言,该数据源控件和数据绑定控件显然很不友好,这里就需要对数据绑定控件的界面进行修改。通过配置数据绑定控件的相应格式可以修改数据绑定控件的外观,如图9-7所示。

  

9-6  配置数据源控件和数据绑定控件             9-7  编辑数据绑定控件界面

开发人员能够自定义数据绑定控件的样式,并且修改某些列的顺序,这里使用了自动套用格式,并将数据绑定控件的width属性设置为100%,这样编写宽度就能够适应浏览器的大小,从而随着浏览器的大小而改变。数据绑定控件配置完成后,值得注意的是,需要勾选SQL语句的高级选项,让数据绑定控件支持编辑、删除和选择,如图9-8所示。

 

9-8  SQL高级选项

配置SQL高级选项后,数据源控件就会自动生成INSERTUPDATEDELETE语句,示例代码如下所示。

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"

        ConnectionString="<%$ ConnectionStrings:mytableConnectionString %>"

        DeleteCommand="DELETE FROM [mynews] WHERE [ID] = @ID"

        InsertCommand="INSERT INTO [mynews] ([TITLE]) VALUES (@TITLE)"

        SelectCommand="SELECT * FROM [mynews]"

        UpdateCommand="UPDATE [mynews] SET [TITLE] = @TITLE WHERE [ID] = @ID">

        <DeleteParameters>

            <asp:Parameter Name="ID" Type="Int32" />

        </DeleteParameters>

        <UpdateParameters>

            <asp:Parameter Name="TITLE" Type="String" />

            <asp:Parameter Name="ID" Type="Int32" />

        </UpdateParameters>

        <InsertParameters>

            <asp:Parameter Name="TITLE" Type="String" />

        </InsertParameters>

    </asp:SqlDataSource>

在完成用户界面的配置后,系统生成的HTML代码如下所示。

    <asp:GridView ID="GridView1" runat="server" AllowPaging="True"

        AutoGenerateColumns="False" BackColor="White" BorderColor="#E7E7FF"

        BorderStyle="None" BorderWidth="1px" CellPadding="3" DataKeyNames="ID"

        DataSourceID="SqlDataSource1" GridLines="Horizontal" Width="100%">

        <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />

        <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />

        <Columns>

            <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False"

                ReadOnly="True" SortExpression="ID" />

            <asp:BoundField DataField="TITLE" HeaderText="TITLE" SortExpression="TITLE" />

        </Columns>

        <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />

        <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />

        <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />

        <AlternatingRowStyle BackColor="#F7F7F7" />

    </asp:GridView>

开发人员可以编写以上HTML实现更多的效果,当确定用户界面编写完毕后,就可以为数据绑定控件选择操作了。

9.6.2  使用GridView显示、删除、修改数据

配置完成用户界面,则需要选择GridView控件的属性并配置GridView任务,如图9-9和图9-10所示。

 

9-9  默认GridView任务   9-10  选择GridView任务

GridView控件支持分页、排序、编辑、删除和选定内容等操作。在GridView控件中,首先必须勾选【分页】复选框,然后再配置PageSize属性才能够让GridView控件支持分页功能。在GridView控件属性中如果勾选了【分页】复选框而不配置PageSize属性,则默认按10条数据分页。勾选了以启用分页、启用编辑、启用删除和启用选定内容后,GridView控件的界面如图9-11所示。

因为在数据源控件配置的过程中,已经配置了支持编辑、删除和选择,所以在数据绑定控件中可以选择启用编辑,启用删除和选定内容等操作,并且系统默认支持更新、插入、删除等操作,运行后如图9-12所示。

  

9-11  编辑数据绑定控件界面           9-12  GridView控件显式

GridView控件支持编辑、删除和选择,当单击编辑时,能够对选择的行进行数据编辑,如图9-13所示。编辑完成后,单击更新按钮则可以执行更新操作,而无需手动编写UPDATE操作,如图9-14所示。

  

9-13  编辑数据                            9-14  执行更新操作

当单击删除时,则会执行DELETE命令,而无需手动编写DELETE命令。GridView控件支持分页、排序、编辑、删除和选定内容,开发人员无需手动编写更新、删除、编辑、也无需手动编写分页,对GridView控件进行缓存设置能够提高应用程序性能,在对数据库的操作,编辑及更新中,GridView控件能够方便开发人员,简化代码。

9.6.3  使用DataList显示数据

DataList控件需要编辑HTML模板来显式数据,虽然在开发上,DataList控件比GridView更加复杂,但是DataList控件能够实现更多效果。相比之下,DataList控件比GridView控件更加灵活,能够进行复杂的事件编写和样式控制。选择【自动套用格式】复选框并将DataList控件的宽度设置为100%,编辑基本的用户界面,如图9-15所示。

通过编辑ItemTemplate能够实现自定义模板,而无需像GridView一样,以表格形式呈现,编辑后运行如图9-16所示。

  

9-15  DataList控件显式数据              9-16  编写ItemTemplate模板

DataList控件执行数据操作基本上同GridView一样,DataList控件与GridView相比只下,有着更灵活的模板方案,能够实现更多的显示效果。

9.6.4  DataList分页实现

DataList控件本身并不带分页实现,如果需要DataList能够实现分页效果,则需要通过代码实现DataList控件的分页。DataList控件分页需要增加若干标签(Label)控件来显式“上一页”,“下一页”等分页所需要的连接,示例代码如下所示。

    <asp:Label ID="Label4" runat="server" Text="Label"></asp:Label>

    <asp:Label ID="Label3" runat="server" Text="Label"></asp:Label>

    <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>

上述代码创建了三个Label控件,这三个控件并无需初始化,这三个控件通过编程实现上一页,下一页的分页形式。如果需要执行分页,则需要编写cs页面代码,cs页面代码如下所示。

            PagedDataSource objPds = new PagedDataSource();

            objPds.DataSource = this.SqlDataSource1.Select(new DataSourceSelectArguments());

            objPds.AllowPaging = true;                                                                   //设置是否允许分页

            objPds.PageSize = 3;                                                                             //设置分页条目数

            int CurPage;                                                                                                       //设置当前页码

            Label2.Visible = false;                                                                            //隐藏标签

            Label4.Visible = false;

上述代码初始化PagedDataSource对象,并将分页控件默认初始化属性Visiblefalse。其中PagedDataSource是封装分页相关属性的类。

            if (Request.QueryString["Page"] != null)                                              //如果传递的页面不为空

            {

                CurPage = Convert.ToInt32(Request.QueryString["Page"]);   //获取传递的参数

            }

            else

            {

                CurPage = 1;                                                                                             //页面的值为1

            }

            objPds.CurrentPageIndex = CurPage - 1;                                          //设置索引

            Label2.Visible = true;                                                                              //显式标签

            Label4.Visible = true;

            Label3.Text = "<a href=/"datalist.aspx/">首页</a>";                          //编写分页

            Label2.Text = "<a href=/"datalist.aspx?page=" + Convert.ToString(CurPage + 1) + "/">下一页</a>";

            Label4.Text = "<a href=/"datalist.aspx?page=" + Convert.ToString(CurPage - 1) + "/">上一页</a>";

上述代码通过传递的Page的值进行分页操作,如果传递的Page的值为不为空,则从数据源控件中读取相应的数据,并显示到数据绑定控件中。

            if (CurPage == 1)                                                                                     //如果只有一个页面

            {

                Label4.Visible = false;                                                                    //隐藏标签

            }

            if (objPds.IsLastPage)

            {

                Label2.Visible = false;

            }

            DataList1.DataSourceID = "";                                                                //重新绑定数据

            DataList1.DataSource = objPds;                                                         //编写DataList的数据源

            DataList1.DataBind();                                                                            //绑定数据源

上述代码通过PagedDataSource对象实现了分页效果,并且将分页条目数设置为3,当数据超过3条时,则会实现分页。运行后如图9-17和图9-18所示。

 

9-17  实现下一页效果                             9-18  实现上一页效果

DataList控件虽然不支持分页,但是能够通过编程实现DataList控件的分页效果。DataList控件在模板编辑和代码开发上虽然没有GridView方便,但是却提高了灵活性,能够自定义分页和数据显示。

9.6.5  使用SQLHelper操作数据库

使用控件,能够方便开发人员的开发和使用,但是很多情况下,不能使用控件来实现,所以很多情况都需要使用ADO.NET操作数据库中的数据,SQLHelper是将ADO.NET中对数据操作的类和对象进行的封装的一个类库,使用SQLHelper能够提高数据库操作的效率。

1.创建SQLHelper

SQLHelper类经常在数据库开发中使用,不仅封装了数据库操作,也提高了数据库操作的安全性,SQLHelper在微软的开发中和DEMO中经常被使用,SQLHelper通常用于多层设计,如果需要使用SQLHelper类,可以到微软官方下载最新的SQLHelper类,也可以自行编写SQLHelper类。如果自行创建SQLHelper类,则在解决方案管理器中新建一个类库,如图9-19所示。

创建类库后,删除自动生成的Class1类,并创建一个新类,类名为SQLHelper,如图9-20所示。

  

9-19  添加类库                   9-20  创建SQLHelper

如果使用下载的SQLHelper类,则可以单击解决方案管理器,单击右键,选择添加现有项,然后选择现有项目添加即可。在SQLHelper类下对数据操作进行封装,开发人员能够使用自己封装的类进行数据操作,示例代码如下所示。

        #region //数据库连接串

        private static readonly string database = “数据库”;                                                      //配置数据库信息

        private static readonly string uid = “用户名”;                                                                           //配置用户名信息

        private static readonly string pwd = “密码”;                                                                   //配置密码信息

        private static readonly string server = “服务器”;                                                            //配置服务器信息

        private static readonly string condb = "server='"+ server +"';database='" + database + "';uid=

        '" + uid + "';pwd='" + pwd + "';Max Pool Size=100000;Min Pool Size=0;

        Connection Lifetime=0;packet size=32767;Connection Reset=false; async=true";      //设置连接字串

        #endregion

        #region//DataAdapter方法 返回DataSet数据集

        /// <summary>

        /// DataAdapter方法 返回DataSet数据集

        /// </summary>

        /// <param name="sqlCmd">SQL语句</param>

        /// <param name="command">操作参数 枚举类型</param>

        /// <returns></returns>

        public static DataSet DataAdapter(string sqlCmd, SDACmd command,              //实现适配器

        string tabName, params SqlParameter[] paraList)

        {

            SqlConnection con = new SqlConnection(condb);                                                      //创建连接对象

            SqlCommand cmd = new SqlCommand();                                                          //创建Command对象

            cmd.Connection = con;                                                                                                      //使用连接对象

            cmd.CommandText = sqlCmd;                                                                               //配置连接字串

            if (paraList != null)

            {

                cmd.CommandType = CommandType.Text;                                               //配置Command类型

                foreach (SqlParameter para in paraList)                                                                //遍历参数

                { cmd.Parameters.Add(para); }                                                                       //添加参数

            }

            SqlDataAdapter sda = new SqlDataAdapter();                                                     //创建适配器

            switch (command)                                                                                                     //查找条件

            {

                case SDACmd.select:                                                                                       //如果为select执行

                    sda.SelectCommand = cmd;

                    break;

                case SDACmd.insert:                                                                                       //如果为insert执行

                    sda.InsertCommand = cmd;

                    break;

                case SDACmd.update:                                                                                     //如果为update执行

                    sda.UpdateCommand = cmd;

                    break;

                case SDACmd.delete:                                                                                      //如果为delete执行

                    sda.DeleteCommand = cmd;

                    break;

            }

            DataSet ds = new DataSet();                                                                                   //创建数据集

            sda.Fill(ds, tabName);                                                                                              //填充数据集

            return ds;                                                                                                                     //返回数据集

        }

在上述代码中,还需要通过一个枚举类型进行switch操作,枚举类型用于判断执行的操作,示例代码如下所示。

        public enum SDACmd { select, delete, update, insert }                                                      //定义枚举类型

定义的枚举类型用于在程序中进行筛选操作,用于指定SQL语句执行的操作。在SQLHelper类中,还需要封装DataReader方法进行DataReader的封装和实现,开发人员能够使用SQLHelper类中的DataReader方法进行数据库的读取,示例代码如下所示。

        public static SqlDataReader ExecReader(string sqlcmd, params SqlParameter[] paraList)

        {

            SqlConnection con = new SqlConnection(condb);                                                      //创建连接对象

            SqlCommand cmd = new SqlCommand();                                                          //创建Command对象

            cmd.Connection = con;                                                                                                      //使用连接

            cmd.CommandText = sqlcmd;                                                                                //配置SQL语句

            if (paraList != null)

            {

                cmd.CommandType = CommandType.Text;                                               //配置Command类型

                foreach (SqlParameter para in paraList)

                { cmd.Parameters.Add(para); }                                                                       //添加参数

            }

            con.Open();                                                                                                                 //打开连接

            SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            return sdr;

        }

上述代码实现了DataReader对象,使用DataReader能够填充SqlDataReader对象并进行数据的循环输出。在ADO.NET中,通常需要执行SQL语句进行数据库的操作,在SQLHelper类中,同样需要封装执行SQL语句的操作以便能够快速执行数据操作。

        public static void ExecNonQuery(string sqlcmd, params SqlParameter[] paraList)

        {

            using (SqlConnection con = new SqlConnection(condb))                                //创建连接对象

            {

                SqlCommand cmd = new SqlCommand();                                                  //创建Command对象

                cmd.Connection = con;                                                                                     //使用连接

                cmd.CommandText = sqlcmd;                                                                        //配置执行类型

                if (paraList != null)

                {

                    cmd.CommandType = CommandType.Text;                                       //配置执行类型

                    foreach (SqlParameter para in paraList)

                    { cmd.Parameters.Add(para); }                                                               //添加参数

                }

                con.Open();                                                                                                         //打开数据连接

                cmd.ExecuteNonQuery();                                                                                 //执行SQL语句

            }

        }

上述代码编写了SQLHelper类操作数据库的函数,通过执行函数并传递参数,即可实现数据库的插入、更新和删除。

2.使用SQLHelper

创建完成SQLHelper类后,需要为应用程序配置SQLHelper的基本属性,代码如下所示。

        private static readonly string database = "mytable";                                                   //配置数据库

        private static readonly string uid = "sa";                                                                         //配置用户名

        private static readonly string pwd ="sa";                                                                        //配置用户会密码

        private static readonly string server = "local";                                                               //配置服务器的值

上述代码为SQLHelper类配置了属性,当使用SQLHelper类时,系统会自动连接数据库,在完成使用后,系统会自动关闭数据库。如果需要在当前项目使用SQLHelper类,则需要添加引用来使用SQLHelper类,右击现有项目,在下拉菜单中选择【添加】选项,在【添加】选项中选择【现有项】选项,在弹出窗口中选择【项目】标签栏,就可以添加相同项目的类库,如图9-21所示。

 

9-21  添加引用

引用添加完毕,在使用SQLHelper页面的CS页面中,需要添加命名空间,命名空间的名称和创建类库的名称相同,如果需要更改名称,可以通过修改类库的属性来修改。示例代码如下所示。

using MYSQL;

引用完毕后,就可以执行SQL语句,使用SQLHelper执行SQL语句非常方便,下面代码演示了如何执行插入、删除操作。

            string strsql = "insert into mynews values ('SQLHelper插入标题')";                         //编写SQL语句

            SQLHelper.ExecNonQuery(strsql);                                                                                  //执行SQL语句

上述代码运行后,则会执行插入操作,相比于ADO.NET,封装后的代码更加简便易懂,删除操作代码如下所示。

            string strsql2 = "delete form mynews where id=3";                                                               //编写SQL语句

            SQLHelper.ExecNonQuery(strsql2);                                                                              //执行SQL语句

当需要执行SELECT语句时,可以通过SQLHelper.DataAdapter获取数据,示例代码如下所示。

            string strsql = "select * from mynews where id=3";                                                               //编写SQL语句

            DataSet ds = SQLHelper.DataAdapter(strsql, SQLHelper.SDACmd.select, "mydatatable");

上述代码通过SQLHelper.DataAdapter获取数据,并创建了一个mydatatable虚拟表,填充DataSet对象。当需要获取DataSet对象中的数据时,和普通的DataSet对象一样。SQLHelper封装了ADO.NET中的许多方法,为开发人员提高了效率,同时也增加了安全性和模块化的特性。

注意:上述代码中的SQLHelper类能够执行的是SQL语句,如果需要执行存储过程,则需要更改SQLHelper类中的相应的CommandType属性的值。

9.7  小结

本章介绍了ADO.NET中操作数据库和执行数据库的一些方法,还介绍了如何编写和执行SQL语句,包括SQL INSERTSQL UPDATESQL DELETE等数据操作语句,另外,本章还介绍了如何通过DataSet数据集实现插入、更新、删除等操作来深入了解ADO.NET。本章通过演示使用控件更新和操作数据库,加强了控件操作数据库的示例,本章还包括:

q      使用ADO.NET操作数据库,介绍了ADO.NET操作数据库的方法。

q      ASP.NET创建和插入记录,介绍了SQL INSERT和数据操作。

q      ASP.NET更新数据库,介绍了SQL UPDATE和数据操作。

q      ASP.NET删除数据,介绍了SQL DELETE和数据操作。

q      使用存储过程,介绍了如何使用存储过程。

q      数据库操作实例,介绍了企业应用中常用的SQLHelper,以及用户操作数据库的配置。

本章还介绍了如何创建和使用企业应用中常用的SQLHelper类、SQLHelper类能够简化数据使用,提高开发效率。下一章中将会讲解如何连接其他数据库。

你可能感兴趣的:(第9章 ASP.NET操作数据库)