第9章 数据库的操纵工具——ADO.NET
本章视频教学录像:55分钟
使用ADO.NET操作数据库是ASP.NET网站开发的重点。本章从ADO.NET的结构出发,介绍如何使用ADO.NET与数据库建立连接、如何使用ADO.NET与数据库进行交互。本章以操作 SQL Server 数据库为例,介绍如何使用 ADO. NET的主要对象,最终使读者通过ADO.NET可以操作常用的数据库,如SQL Server、Access、Oracle等。
本章要点(已掌握的在方框中打钩)
□ 什么是ADO.NET
□ ASP.NET 与 SQL Server 数据库的连接
□ SqlConnection 对象
□ SqlCommand 对象
□ SqlDataReader 对象
□ SqlDataAdapter 对象
□ DataTable 对象
□ DataSet 对象
9.1 ADO.NET简介
本节视频教学录像:5分钟
对数据库操作是ASP.NET网站开发中的重中之重,ADO.NET则是ASP.NET网站通往数据库之间的桥梁。
9.1.1 什么是ADO.NET
ADO.NET 的名字起源于 ADO(ActiveX Data Objects),这是一个广泛的类组,用于在以往的Microsoft技术中访问数据。ADO.NET是在ADO的基础上发展的新一代数据存取技术,是在.NET开发环境中优先使用的数据访问接口。通俗地讲,ADO.NET就是设计了一系列对各种类型数据的访问形式,并提供了对应的类,在类中提供了与对应数据交互的属性和方法,编程者可以通过这些属性和方法很方便地对各种数据源进行存取操作,例如SQL数据库、Access数据库、Oracle数据库、XML文件等。
在ADO.NET中,可以使用多种.NET Framework数据提供程序来访问数据源。.NET Framework提供的数据提供程序主要有以下几种。
⑴SQL Server .NET Framework数据提供程序:使用System.Data.SqlClient命名空间,用于访问SQL Server数据库。
⑵Oracle .NET Framework数据提供程序:使用System.Data.OracleClient命名空间,用于访问Oracle数据库。
⑶OLE DB .NET Framework数据提供程序:使用System.Data.OleDb命名空间,用于访问OLE DB公开的数据源,例如Access数据库等。
⑷ODBC .NET Framework数据提供程序:使用System.Data.Odbc命名空间,用于访问ODBC公开的数据源,例如Visual FoxPro数据库等。
在这些数据提供程序中,我们主要使用SQL Server .NET Framework数据提供程序和OLE DB .NET Framework数据提供程序。
ADO.NET的最大特点就是支持对数据的无连接方式的访问,减少了与数据库的活动连接数目,从而减少了多个用户争用数据库服务器上有限资源的可能性。
9.1.2 ADO.NET的结构
ADO.NET的结构如图所示。
ADO.NET有5个主要的对象。
⑴Connection:用于连接到数据库或其他数据源。
⑵Command:用于在数据库中检索、更新、删除、插入数据等。
⑶DataReader:从数据库或数据源提供数据流。这些数据是只读属性。DataReader对象没有公用的构造函数,因而不能像其他类对象一样可以通过构造函数来实例化,只能使用Command对象中的ExecuteReader方法来创建一个DataReader对象。DataReader对象适用于与数据源保持连接方式下的顺序读取数据。
⑷DataAdapter:用于将数据源中的数据填充到DataSet中,并将在DataSet中的数据更新后保存到数据库中。通常称DataAdapter为“数据适配器”,把DataAdapter看作是DataSet和数据库之间的桥梁。
⑸DataSet:数据集是驻留在内存中的数据库,其中包含表、视图、表之间的关系等。通常在无连接方式下使用DataSet。
提示
ADO.NET的5个对象可以形象地记为:连接“Connection”,执行“Command”,读取“DataReader”,分配.“DataAdapter”,填充“DataSet”。这正是ADO.NET对数据库操作的一般步骤。
9.2 ADO.NET与数据库的连接
本节视频教学录像:10分钟
在ADO.NET中,对数据库进行操作时,需要事先使用Connection请求连接,以便进行客户端相关信息的认证,比如用户名、密码以及访问数据库等。本节介绍几种常用数据库的连接方法。
9.2.1 ADO.NET与SQL Server数据库的连接
SQL Server .NET Framework 数据提供程序位于 System.Data.SqlClient 命名空间中,它使用SqlConnection对象与Microsoft SQL Server数据库建立连接。通常有以下两种形式的连接字符串。
1. 在连接字符串中指定服务器名、用户ID、用户密码、数据库名等信息
例如:
string connstring="server=servername;uid=username;pwd=password;database=dbname";
SqlConnection conn=new SqlConnection(connstring);
conn.Open();
或者:
string connstring="Data Source=servername;uid=username;pwd=password;Initial Catalog=dbname";
SqlConnection conn=new SqlConnection(connstring);
conn.Open();
说明:连接字符串中的“servername”是指局域网中提供SQL Server服务的服务器和SQL Server的实例名;如果一台机器只安装一个SQL Server的实例,也可以直接指定服务器名;如果安装SQL Server的服务器是本机,则可写为“localhost”,否则可以用IP地址或域名指定。“username”和“password”是指登录SQL Server数据库所使用的用户名和密码。“dbname“是指所要连接到的数据库名称。
【范例9-1】创建一个ASP.NET Web应用程序,利用DropDownList控件将Student数据库中的Student表中的学号字段中的所有记录显示出来。
⑴在SQL Server 2008中,以sa账户登录,附加Student数据库(随书光盘)。
⑵在Visual Studio 2010中,新建ASP.NET网站,添加一个不使用母版页的页面Default2.aspx,切换到页面设计视图,向页面上拖放一个DropDownList控件,如图所示。
⑶打开Default2.aspx.cs文件,在Default2.aspx.cs文件中代码的最上方添加引用命名空间的代码。
using System.Data;
using System.Data.SqlClient;
⑷在Page_Load事件中添加程序执行代码。全部源代码如下。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 if (!Page.IsPostBack) //判断是否是首次加载页面
04 {
05 //与数据库连接字符串
06 string connStr= "server=.\\sqlexpress;uid=sa;pwd=123;database=Student";
07 SqlConnection conn= new SqlConnection(connStr); //创建SqlConnection对象
08 conn.Open(); //打开与数据库的连接
09 SqlCommand cmd= new SqlCommand(); //创建SqlCommand对象
10 cmd.Connection= conn;
11 cmd.CommandText= "select * from studentinfo"; //执行的SQL语句
11 SqlDataReader dr= cmd.ExecuteReader(); //创建SqlDataReader对象
12 this.DroDownListNO.DataSource=dr; //将DropDownListNO控件与数据源绑定
13 this.DroDownListNO.DataTextField= "SNO";
14 //在ASP.NET程序中,数据源与控件绑定时,此句必不可少,否则在页面上显示不出结果
15 this.DroDownListNO.DataBind();
16 if (conn.State==ConnectionState.Open)
17 {
18 conn.Close(); //判断连接状态,若连接就关闭连接
19 }
20 }
21 }
【运行结果】
按【F5】键调试并运行,浏览器中的运行结果如图所示。
【范例分析】
本范例中,第6行就是设置ADO.NET与SQL Server数据库连接的连接字符串;第7~12行使用了 ADO.NET 与 SQL Server 数据库访问的对象,分别是 SqlConnection 对象、SqlCommand 对象和SqlDataReader对象,这些对象将在下节重点介绍;第13~16行是将获取的数据源绑定到DropDownList控件上显示出来;第17~20行是用来判断ADO.NET与SQL Server数据库的连接状态,如果处于连接状态就断开连接。
提示
在Web应用程序开发中,通常将与数据库连接的连接字符串写在Web.Config文件中,例如将上面范例中的连接字符串写在Web.config文件中。
<connectionStrings>
<add name="ConnStr"connectionString="server=localhost;uid=sa;pwd=123;database=Student"/>
< /connectionStrings>
在程序中的引用方式为:
//与数据库连接字符串
string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
//创建SqlConnection对象
SqlConnection conn = new SqlConnection(connStr);
2. 在连接字符串中指定数据库服务器名、集成Windows安全认证方式、数据库名等信息
例如:
string connStr="server= servername;Integrated Security=SSPI;database= dbname ";
SqlConnection conn=new SqlConnection(connStr);
conn.Open();
或者:
string connStr="Data Source= servername;Integrated Security=SSPI;Initial Catalog= dbname ";
SqlConnection conn=new SqlConnection(connStr);
conn.Open();
说明:连接字符串中的Integrated Security=SSPI表示集成Windows系统安全认证方式,这种连接方式也成为“可信任连接”,这是连接到SQL Server数据库更可靠的方法,因为它不会在连接字符串中暴露用户的ID以及密码。
【范例9-2】创建一个ASP.NET 网站,利用GridView控件将Student数据库中的StudentInfo表中的学号字段中的所有记录显示出来。
⑴在SQL Server 2008中,以sa账户登录,附加Student数据库(随书光盘\Simple\ch07)。
⑵在Visual Studio 2010中,新建ASP.NET网站,添加一个不使用母版页的页面Default2.aspx,切换到页面设计视图,向页面上拖放一个GridView控件,如图所示。
⑶在Web.config文件中添加以下<connectionStrings/>节点代码。
01 <connectionStrings>
02 <add name="ConnStr" connectionString="server=.\sqlexpress;
03 Integrated Security=SSPI;database=Student"/>
04 < /connectionStrings>
⑷打开Default2.aspx.cs文件,在Default2.aspx.cs文件中代码的最上方,添加需要引用的命名空间。
01 using System.Data;
02 using System.Data.SqlClient;
03 using System.Configuration;
⑸在Page_Load事件中添加程序执行代码。全部源代码如下(代码9-2.txt)。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 if (!Page.IsPostBack) //判断是否是首次加载页面
04 {
05 //与数据库连接字符串
06 string connStr=ConfigurationManager.
07 ConnectionStrings["ConnStr"].ConnectionString;
08 //创建SqlConnection对象
09 SqlConnection conn= new SqlConnection(connStr);
10 conn.Open(); //打开与数据库的连接
11 //创建SqlDataAdapter对象
12 SqlDataAdapter ad= newSqlDataAdapter("Select * from StudentInfo", conn);
13 //创建DataSet对象
14 DataSet ds= new DataSet();
15 ad.Fill(ds); //填充DataSet对象
16 //对GridView对象绑定数据源
17 this.GridView1.DataSource=ds;
18 //此句必须有,否则页面上显示不出数据
19 this.GridView1.DataBind();
20 if (conn.State==ConnectionState.Open)
21 { //判断连接状态,若连接就关闭连接
22 conn.Close();
23 }
24 }
25 }
【运行结果】
按【F5】键调试并运行,结果如图所示。
【范例分析】
本范例中,步骤⑶的程序代码是将连接字符串写在Web.config文件的<connectionStrings/>节中,目的是将其作为全局变量使用,在Web开发中非常实用。步骤⑶的第06行就是从Web.config中读取数据库连接的连接字符串;第8~15行使用了ADO.NET与SQL Server数据库访问的对象,分别是SqlConnection对象、SqlCommand对象和DataSet对象,这些对象将在下节重点介绍;第16~19行是将获取的数据源绑定到GridView控件上显示出来;第21~23行是用来判断ADO.NET与SQL Server数据库的连接状态,如果处于连接状态就断开连接。
9.2.2 ADO.NET与Access数据库的连接
OLE DB .NET Framework数据提供程序位于System.Data.OleDb命名空间中,可以通过OLE DB提供程序与OLE DB数据源进行通信,例如Access数据库等。
使用Access数据库时连接字符串的形式如下。
"Provider=Microsoft.Jet.OLE DB.4.0; Data Source=AccessDatabaseName"
说明:连接字符串中的“Microsoft.Jet.OLEDB.4.0”表示使用微软提供的Access数据库提供程序。“AccessDatabaseName”表示Access数据库文件名(包含完整的路径)。
提示
在Data和Source之间要有一个空格。
【范例9-3】创建一个 ASP.NET Web 应用程序,利用 GridView 控件将Student数据库中的StudentInfo表中的学号字段中的所有记录显示出来。
⑴在Visual Studio 2010中,新建ASP.NET Web网站。在项目App_Data文件夹中,使用Access 2003创建一个Student.mdb数据库(数据库见随书光盘)。
⑵添加一个不使用母版页的页面 Default2.aspx,切换到页面设计视图,向页面上拖放一个GridView控件。
⑶在Default2.aspx.cs文件中添加引用命名空间。
Using System.data;
using System.Data.OleDb; //操作Access数据库必须添加此命名空间
⑷打开Default2.aspx.cs文件,在Page_Load事件中添加程序执行代码。全部源代码如下(代码9-3.txt)。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 if (!Page.IsPostBack) //判断是否是首次加载页面
04 {
05 //与数据库连接字符串,在本示例中数据库文件放在
06 //网站数据目录,即与web.config文件在同一目录下
07 string ConnStr=@"Provider=Microsoft.Jet.OLEDB.4.0;
08 Data Source="+Server.MapPath(@"Student.mdb");
09 //创建OleDbConnection对象
10 OleDbConnection conn= new OleDbConnection(ConnStr);
11 conn.Open();
12 //创建OleDbCommand对象
13 OleDbCommand cmd= new OleDbCommand();
14 cmd.Connection= conn;
15 cmd.CommandText= "Select * from StudentInfo";
16 //创建OleDbDataAdapter对象
17 OleDbDataAdapter ad= new OleDbDataAdapter(cmd);
18 DataSet ds= new DataSet();
19 //填充DataSet对象
20 ad.Fill(ds);
21 this.GridView1.DataSource=ds;
22 //此句必须有,否则页面上显示不出数据
23 this.GridView1.DataBind();
24 if (conn.State==ConnectionState.Open)
25 { //判断连接状态,若连接就关闭连接
26 conn.Close();
27 }
28 }
29 }
【运行结果】
按【F5】键调试并运行,结果如图所示。
【范例分析】
本范例中,第7、8行就是从Web.config中读取数据库连接的连接字符串;第9~20行使用了 ADO.NET 与 OLE DB 数据源(Access 数据库属于 OLE DB 数据源)的访问对象,分别是OleDbConnection对象、OleDbCommand对象和DataSet对象,这些对象的使用与SqlConnection对象、SqlCommand对象等的用法一致;第21~23行是将获取的数据源绑定到GridView控件上显示出来;第24~27行是用来判断ADO.NET与Access数据库的连接状态,如果处于连接状态就断开连接。
9.3 ADO.NET与SQL Server数据库的交互
本节视频教学录像:23分钟
本节以操作SQL Server数据库为例,从ADO.NET数据访问对象出发,介绍如何使用ADO.NET与数据库交互,最后设计一个数据库访问类,完整地介绍如何使用ADO.NET操作数据库。
为了方便应用程序对 SQL Server 数据库的操作,ADO.NET 提供了许多对象模型,比较常用的有SqlConnection对象、SqlCommand对象、SqlDataAdapter对象、SqlDataReader对象、SqlCommandBuilder对象、SqlParameter对象和SqlTransaction对象等。这些对象提供了对SQL Server数据源的各种不同的访问功能,全部归类于System.Data.SqlClient命名空间下,使用时必须引用该命名空间。
9.3.1 使用SqlConnection对象连接数据库
要想访问数据库,首先必须连接到数据库,SqlConnection类提供了对SQL Server数据库的连接。在使用SqlConnection对象连接SQL Server数据库时,程序员需要提供一个连接字符串。连接字符串由一系列关键字和值组成,各关键字之间用分号隔开,关键字不区分大小写。
例如,建立与SQL Server数据库的连接。
string connstring="Data Source=servername;uid=username;pwd=password;Initial Catalog=dbname";
SqlConnection conn=new SqlConnection(connstring);
conn.Open();
例如,判断连接状态,如果连接状态为Open则关闭连接。
if (conn.State == ConnectionState.Open)
{ //判断连接状态,若连接就关闭连接。
conn.Close();
}
9.3.2 使用SqlCommand对象在连接状态下操作数据
与数据库连接成功后,就可以对数据库中的数据进行插入、更新、删除、查询等操作。在ADO. NET中,有两种操作数据库的方式,一种是采用无连接的方式,即先将数据库中的数据读取到本机的DataSet中,或者直接读取到本机的DataTable中;另一种就是在保持连接的方式下,通过执行指定的SQL语句完成需要的功能。
无论采用哪种方式,都可以通过SqlCommand对象提供的方法传递对数据库操作的命令,并返回命令执行的结果。操作命令的类型可以是SQL语句,也可以是存储过程。
在保持连接的方式下,操作数据库的一般步骤如图所示。
SqlCommand对象提供有多种完成对数据库操作的方法。
1. ExecuteNonQuery方法
该方法执行SQL语句,并返回因操作所受影响的行数。一般将其用于使用Update、Insert、Selected、Delete等语句直接操作数据库中的表数据。ExecuteNonQuery方法对于Update、Insert和Delete等语句,其返回值为该命令所影响的行数;而对于其他类型的语句(Select等),其返回值为-1。如果发生回滚,其返回值也为-1。
【范例9-4】将Student数据库中StudentInfo表中性别为“女”的学生成绩增加分,分值自定。
⑴在SQL Server 2008中,以sa账户登录,附加Student数据库(见随书光盘)。
⑵创建一个ASP.NET空网站,添加一个Default.aspx页面,向页面中添加一个GridView控件、一个Button控件、一个Label控件和一个TextBox控件,ID修改为txtScore,页面设计如图所示。
⑶在Default.aspx.cs文件中,添加命名空间的引用代码和类的私有字段。
01 using System.Data.SqlClient;
02 using System.Data;
03 //添加类一级字段,即页面级变量
04 string ConnStr= "server=.\\sqlexpress; IntegratedSecurity=SSPI;database=Student";
⑷打开Default.aspx.cs文件,在Page_Load事件中添加程序执行代码(代码9-4-1.txt)。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 SqlConnection conn= new SqlConnection(ConnStr);
04 SqlCommand cmd= new SqlCommand();
05 cmd.Connection= conn;
06 cmd.CommandText= "Select * from StudentInfo";
07 try
08 {
09 conn.Open();
10 SqlDataReader dr= cmd.ExecuteReader();
11 this.GridView1.Caption= "加分前的学生信息表 ";
12 this.GridView1.DataSource=dr;
13 this.GridView1.DataBind();
14 }
15 catch (SqlException sex)
16 {
17 throw sex;
18 }
19 finally
20 {
21 if (conn.State==ConnectionState.Open)
22 {
23 conn.Close();
24 }
25 }
26 }
⑸双击Button控件,在btnAdd_Click事件中添加执行代码(代码9-4-2.txt)。
01 protected void button1_Click(object sender,EventArgs e)
02 {
03 SqlConnection conn= new SqlConnection(ConnStr);
04 SqlCommand cmd= new SqlCommand();
05 cmd.Connection= conn;
06 cmd.CommandText= "Update StudentInfo Set Score=Score+"+
07 this.txtScore.Text.Trim()+"WhereSex='女 '";
08 try
09 {
10 conn.Open();
11 int iValue= cmd.ExecuteNonQuery();
12 if (iValue> 0)
13 {
14 cmd.CommandText= "Select * fromStudentInfo";
15 SqlDataReader dr= cmd.ExecuteReader();
16 this.GridView1.Caption= "加分后学生信息表 ";
17 this.GridView1.DataSource=dr;
18 this.GridView1.DataBind();
19 Response.Write("<script>window.alert('加分成功! ')< /script>");
20 }
21 }
22 catch (SqlException sex)
23 {
24 throw sex;
25 }
26 finally
27 {
28 if (conn.State==ConnectionState.Open)
29 {
30 conn.Close();
31 }
32 }
33 }
【运行结果】
按【F5】键调试并运行。加分之前的界面如图所示。
在txtScore文本框中输入“10”,单击【加分】按钮,即可实现将所有女生的分数加分,如图所示。
【范例分析】
本范例中,第4、5、6行是创建SqlCommand对象,设置连接、设置Sql查询语句,目的是检索出加分前学生的信息;第7~14行的try语句块是打开连接,使用SqlDataReader对象来获取数据源,然后将数据源绑定到GridView控件上显示出来;第15~18行的catch语句块是捕获异常,一旦操作失败,则抛出异常;第19~25行的finally语句块是无论程序是否正常运行还是抛出异常,均要执行finally语句块来关闭与数据库的连接;第32、33行用于设置Sql更新语句;第34~47行的try语句块是通过SqlCommand对象的ExecuteNonQuery方法更新数据库,然后重新将数据源绑定到GridView控件并显示出来。
释放与数据库的连接除了使用SqlConnection对象的Close方法外,还有一种方法就是使用using语句。在using语句中不再使用Close方法,一旦using模块结束,系统会立即关闭与相关对象的相关连接,并立即释放在using模块中指定的资源。
using语句的一般形式如下。
using(创建一个或多个需要使用后立即释放资源的对象,多于一个对象时,各对象之间用逗号分隔)
{
功能模块
}
或者创建一个或多个对象。
using(使用的对象,多于一个对象时,各对象间用逗号分隔)
{
功能模块
}
在【范例9-4】中的btnAdd_Click事件中使用using语句如下。
01 protected void button1_Click(object sender,EventArgs e)
02 {
03 using (SqlConnection conn= new SqlConnection(ConnStr))
04 {
05 SqlCommand cmd= new SqlCommand();
06 cmd.Connection= conn;
07 cmd.CommandText= "UpdateStudentInfoSetdeptname=’"+
08 this.txtScore.Text.Trim()+ "’Wheregender='女 '";
09 try
10 {
11 conn.Open();
12 int iValue= cmd.ExecuteNonQuery();
13 if (iValue> 0)
14 {
15 cmd.CommandText= "Select * fromStudentInfo";
16 SqlDataReaderdr= cmd.ExecuteReader();
17 this.GridView1.Caption= "加分后的学生信息表 ";
18 this.GridView1.DataSource=dr;
19 this.GridView1.DataBind();
20 Response.Write("<script>window.alert('加分成功! ')< /script>");
21 }
22 }
23 catch (SqlException sex)
24 {
25 throw sex;
26 }
27 }
28 }
提示
这里的using语句与引用命名空间时使用的using语句的含义是不同的。
2. ExecuteReader方法
ExecuteReader方法提供了顺序读取数据库中数据的方法。该方法根据提供的Select语句,返回一个SqlDataReader对象,编程者可以使用SqlDataReader对象的Read方法,循环依次读取每条记录中各字段(列)的内容。
【范例9-5】创建一个ASP.NET 空网站,添加一个Default.aspx页面,在页面上添加一个ListBox,在ListBox控件中显示DepartName表的编码对照表。
⑴在SQL Server 2008中附加Student数据库。在Visual Studio 2010中,新建ASP.NET空网站,添加一个Default.aspx页面,然后切换到页面设计视图,向页面中添加一个ListBox控件,ID修改为lbxCodeDepartment。
⑵在代码编辑文件中,添加命名空间的引用代码和类一级的私有字段。
using System.data;
using System.Data.SqlClient;
//添加类一级字段,即页面级变量
string ConnStr ="server=.\\sqlexpress; Integrated Security=SSPI;database=Student”;
⑶打开Default.aspx.cs文件,在Page_Load事件中添加程序执行代码(代码9-5.txt)。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 using (SqlConnection conn= new SqlConnection(ConnStr))
04 {
05 SqlCommand cmd= new SqlCommand();
06 cmd.Connection= conn;
07 cmd.CommandText= "Select * from DepartName";
08 try
09 {
10 conn.Open();
11 SqlDataReader dr= cmd.ExecuteReader();
12 while (dr.Read())
13 {
14 this.lbxCodeDepartment.Items.
15 Add(string.Format("[{0}]\t{1}",dr[0],dr[1]));
16 }
17 }
18 catch (SqlException sex)
19 {
20 throw sex;
21 }
22 }
23 }
【运行结果】
按【F5】键调试并运行,结果如图所示。
【范例分析】
本范例中,第7、8、9行是创建SqlCommand对象,设置连接、设置Sql查询语句,目的是将学生院系信息检索出来;第13~19行是使用SqlDataReader对象获取数据源,通过while循环将院系记录一条一条读取出来,使用ListBox控件显示出来。
提示
除了通过使用SqlDataReader对象和索引方式获取每条记录中各列的值之外,还可以使用SqlDataReader对象的GetValue方法。此外,SqlDataReader类中提供了针对获取每一种数据类型的值的方法,例如获取的值的类型是字符串,则可使用SqlDataReader类提供的GetString方法。
3. ExecuteScaler方法
ExecuteScaler方法也是用于执行Select查询,得到的返回结果是检索数据的第1行、第1列的元素,即返回结果为一个值的情况。通常用来返回Count、Sum等系统函数的执行结果及仅需要返回一个值的情形。
【范例9-6】创建一个ASP.NET空网站,在ListBox控件中显示StudentInfo表中成绩及格的学生人数和总分。
⑴在SQL Server 2008中附加Student数据库。在Visual Studio 2010中,新建ASP.NET空网站,添加一个Default.aspx页面,然后切换到页面设计视图,向页面中添加一个ListBox控件。
⑵在代码编辑文件中,添加命名空间的引用代码和类一级的私有字段。
using System.Data.SqlClient;
⑶打开Default.aspx.cs文件,在Page_Load事件中添加程序执行代码。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 string ConnStr=
04 "server=.\\sqlexpress; Integrated Security=SSPI;database=Student”;
05 using (SqlConnection conn= new SqlConnection(ConnStr))
06 {
07 SqlCommand cmd= new SqlCommand();
08 cmd.Connection= conn;
09 cmd.CommandText=
10 "Select Count(NO) from StudentInfo Where Score>=60";
11 conn.Open();
12 object oCount= cmd.ExecuteScaler(); //获取及格学生的总人数
13 this.lbxCodeDepartment.Items.Add("人数 : "+oCount.ToString());
14 cmd.CommandText=
15 "Select Sum(Score) from StudentInfo Where Score>=60";
16 object oScore= cmd.ExecuteScaler(); //获取及格学生的总分
17 this.lbxCodeDepartment.Items.Add("总分 : "+ oScore.ToString());
18 }
19 }
【运行结果】
按【F5】键调试并运行,结果如图所示。
【范例分析】
本范例中,第7、8、9、10行是创建SqlCommand对象,设置连接、设置Sql检索语句,目的是将学生院系信息检索出来并统计出学生总人数;第12、13行是使用ExecuteScaler方法获取学生总人数,添加到ListBox控件中;第14~17行是重新设置SqlCommand对象的CommandText属性,来获取学生的总分并使用ExecuteScaler方法获取总分,最后添加到ListBox控件中。
9.3.3 使用SqlDataAdapter对象在无连接状态下操作数据
当需要进行大量的数据处理或者在动态的数据交互过程的场合时,可以使用SqlDataAdapter对象通过无连接的方式完成数据库和本机内存中DataSet之间的交互。该对象通过Fill方法将数据源中的数据填充到本机内存中的DataSet或者DataTable中,填充完成自动与数据库服务器断开连接,然后就可以在与数据库服务器不保持连接的情况下,对DataSet中的数据表或对DataTable进行浏览、插入、修改、删除等操作。操作完成,如果需要更新数据库,则可再利用SqlDataAdapter类提供的Update方法把DataSet或者DataTable中处理的结果更新到数据库中。
使用无连接方式操作数据库的一般步骤如图所示。
【范例9-7】创建一个ASP.NET Web应用程序,使用SqlDataAdapter对象在无连接方式下对数据库Student中的StudentInfo表进行操作,添加新记录。
⑴在SQL Server 2008中附加Student数据库。在Visual Studio 2010中,新建ASP.NET空网站,添加一个Default.aspx页面,然后切换到页面设计视图。页面设计如图所示。
⑵在代码编辑文件中,添加命名空间的引用代码和类一级的私有字段。
using System.Data.SqlClient;
string ConnStr ="server=.\\sqlexpress; Integrated Security=SSPI;database=Student";
⑶在Page_Load事件中添加程序执行代码。
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 if (!Page.IsPostBack)
04 {
05 using (SqlConnection conn= new SqlConnection(ConnStr))
06 {
07 SqlDataAdapter ad= new SqlDataAdapter("Select * from StudentInfo", conn);
08 SqlCommandBuilder builder= new SqlCommandBuilder(ad);
09 DataTable dt= new DataTable();
10 ad.Fill(dt);
11 this.GridView1.DataSource=dt;
12 this.DataBind();
13 }
14 }
15 }
⑷双击Button控件,编写btnAddNew_Click事件,完成添加新记录功能(代码9-7.txt)。
01 protected voidbtnAddNew_Click(object sender,EventArgs e)
02 {
03 object oName;
04 using (SqlConnection conn= new SqlConnection(ConnStr))
05 {
06 SqlCommand cmd= new SqlCommand();
07 cmd.Connection= conn;
08 conn.Open();
09 cmd.CommandText= "Select ID from DepartName Where
10 DName='"+this.txtDepartment.Text.Trim()+"'";
11 oName= cmd.ExecuteScalar(); //根据学院名称获取学院编码
12 }
13 using (SqlConnection conn= new SqlConnection(ConnStr))
14 {
15 SqlDataAdapter ad= new SqlDataAdapter
16 ("Select * from StudentInfo", conn); //创建SqlDataAdapter对象
17 SqlCommandBuilder builder= new SqlCommandBuilder(ad);
//创建SqlCommandBuilder对象
18 //通过SqlCommandBuilder对象为SqlDataAdapter对象生成 Insert命令
19 ad.InsertCommand=builder.GetInsertCommand();
20 DataTable dt= new DataTable();
21 ad.Fill(dt);
22 this.txtNO.Focus();
23 DataRow row=dt.NewRow(); //创建一条新记录
24 row[0]= this.txtNO.Text.Trim(); //为学号字段赋值
25 row[1]= this.txtName.Text.Trim(); //为姓名字段赋值
26 row[2]= this.txtSex.Text.Trim(); //为性别字段赋值
27 row[3]= this.txtBirthday.Text.Trim(); //为出生日期字段赋值
28 row[4]= oName; //为院系编码字段赋值
29 row[5]= this.txtScore.Text.Trim(); //为分数字段赋值
30 dt.Rows.Add(row); //向表中添加新建的记录
31 ad.Update(dt); //通过SqlDataAdapter对象的Update方法将内存中的表更新到数据库中
32 this.GridView1.DataSource=dt;
33 this.DataBind(); //重新绑定数据源
34 Response.Write("<script>window.alert('添加成功! ')< /script>");
35 }
36 }
【运行结果】
按【F5】键调试并运行。
添加前的记录如图所示。
输入新的学生记录后单击【添加】按钮,将在上面的GridView控件中显示出新添加的学生信息,并将新记录更新到数据库中。添加后的运行结果如图所示。
数据库中的记录如图所示。
【范例分析】
本范例中,使用SqlDataAdapter对象来实现无连接方式操作数据库。第4~12行是根据用户输入的学院名称获取学院编码;第15、16行是创建SqlDataAdapter对象;第17、18、19行是创建SqlCommandBuilder对象,并由此对象为SqlDataAdapter对象生成InsertCommand,用于向数据库中添加新记录;第20行是使用SqlDataAdapter对象将数据表填充DataTable对象;第23~30行是获取用户输入的新记录;第31行是调用SqlDataAdapter对象的Update方法更新数据库;第32、33、34行是重新将数据源绑定到GridView控件并显示出来。
9.3.4 使用DataTable对象操作数据
ADO.NET有一个非常突出的特点,就是可以在与数据库断开连接的方式下通过DataSet或DataTable对象进行数据处理,当需要更新数据库时才重新和数据源进行连接,并更新数据源,更新完成后自动断开连接。
DataTable对象表示保存在本机内存中的表,它提供了对表中数据的各种操作。与关系数据库中的表结构类似,DataTable对象也包括行、列以及约束关系等属性。在DataTable对象中可以包含多个DataRow对象,每一个DataRow对象都表示每一行;同样在DataTable对象中也包含多个DataColumn对象,每一个DataColumn对象都表示一列,每列也都有一个固定的DataType属性,表示该列的数据类型。
程序员可以通过编写代码直接将数据从数据库填充到DataTable对象中,也可以将DataTable对象添加到现有的DataSet对象中。在断开连接的方式下,DataSet对象提供了和关系数据库一样的关系数据模型,在代码中可以直接访问DataSet对象中的DataTable对象,也可以添加、删除DataTable对象。
1. 创建DataTable对象
一般情况下,可以通过以下两种方式创建DataTable对象。
⑴使用DataTable类的构造函数来创建DataTable对象。
DataTable dt=new DataTable();
⑵使用DataSet类的Tables属性提供的Add方法创建DataTable对象。
DataSet ds=new DataSet();
DataTable dt=ds.Tables.Add("tbName");
2. 在DataTable对象中添加列
由于DataTable对象的每一列都是一个DataColumn对象,因此,可以通过以下两种方式在DataTable对象中添加列。
⑴使用DataColumn类的构造函数来创建DataColumn对象。
DataColumn column=new DataColumn();
⑵使用DataTable类的Columns属性提供的Add方法创建DataColumn对象。
DataTable dt=new DataTable();
DataColumn column=dt.Columns.Add("colName",typeof(SqlTypes.TypeName));
3. 在DataTable对象中设置主键
关系数据库中的表都有一个主键,用来唯一标识一条记录。在程序中,可以通过DataTable类提供的PrimaryKey属性来设置DataTable对象的主键。需要注意的是:PrimaryKey属性的返回值是一个DataColumn对象组成数组,因为表中的主键可以由多个键组成。例如:
DataColumn[] Key=new DataColumn[1]; //创建字段数组,因为表的主键不一定只用一个字段标识
Key[0]=dt.Columns["ID"]; //给数组中的元素赋值,且该数组中只有一个元素
dt.PrimaryKey=Key; //设置主键
4. 在DataTable对象中添加行
由于DataTable对象的每一行都是一个DataRow对象,所以创建行时可以先用DataTable对象的NewRow方法创建一个DataRow对象,并设置好新行中各列的数据,然后使用DataTable对象Rows属性提供的Add方法将DataRow对象添加到表中。例如:
DataTable dt=new DataTable();
DataRow Row=dt.NewRow();
Row["SName"]="张三";
Row["年龄"]=20;
dt.Rows.Add(Row);
注意
由于在SQL Server数据库提供的数据类型中,有些数据类型与公共语言运行库(CLR)不相同,因此要将动态生成的表数据保存到数据库中,还需要使用System.Data.SqlTypes命名空间提供的SQL Server数据类型。
例如:
DataColumn Col=new DataColumn("ID",typeof(SqlTypes.SqlInt32));
DataColumn Col=new DataColumn("SName",typeof(SqlTypes.SqlString));
9.3.5 使用DataSet对象操作数据
与关系数据库中的数据库结构类似,DataSet也是由表、关系和约束的集合组成的。就像可以将多个表保存到一个数据库中进行管理一样,也可以将多个表保存到一个DataSet对象中进行管理,此时DataSet对象中的每个表都是一个DataTable对象。当多个表之间具有约束关系或同时需要对多个表进行处理时,使用DataSet就显得异常重要。
1. 创建DataSet对象
可以通过DataSet类的构造函数创建DataSet对象,例如:
DataSet ds=new DataSet();
另外,还可以在【解决方案资源管理器】中利用向导来创建DataSet对象。具体步骤为:右击【解决方案资源管理器】中的项目选择【新建项】在【模板】中选择“数据集”输入数据集的名称后单击【添加】按钮即可。
需要注意的是:利用向导生成的DataSet是一个强类型的DataSet,以及一对或多对强类型的DataTable和TableAdapter的组合,其扩展名为 .xsd。类型化的DataSet是一个自动生成的类。同时,对于DataSet对象中的每个表,还生成了特定于该DataSet的专用类,而且每个类都为相关的表提供了特定的架构、属性和方法。这是在编译时检查相关语法和提供相关智能帮助的基础,为设计带来了很大的方便。在应用设计中,我们应尽可能地使用自动生成的强类型的DataSet、DataTable以及与DataTabe对应的TableAdapter。
2. 填充DataSet对象
创建DataSet对象后,就可以使用DataAdapter对象把数据导入到DataSet对象中,使用方法是调用DataAdapter对象的Fill方法。例如:
SqlDataAdapter ad=new SqlDataAdapter("Select * from studentinfo",conn);
DataSet ds=new DataSet();
ad.Fill(ds, "StudentInfo");
9.3.6 数据访问接口
数据访问层是3层开发架构的最底层,专门负责与数据库进行交互操作,数据访问层与数据库之间就是数据访问接口。数据访问接口实际上起到了承上启下的作用,其主要功能如下。
⑴向下:为数据库提供要进行操作的SQL命令和参数,供数据库底层进行操作、处理。
⑵向上:为数据访问层提供数据库底层操作、处理后的结果。
说到数据访问接口,就不得不说一说SQLHelper类。SQLHelper类作为数据库通用访问组件的基础类,是一个抽象类,本身不能实例化对象,可直接调用,主要用于对SQL Server数据库进行读写访问。作为一个数据访问接口,其功能不仅强大,而且属于开源代码类,其源代码对用户完全开放,用户可以根据自己的需要对SQLHelper类的功能进行修改、补充。
SQLHelper类的源代码可参阅本书附带的素材(随书光盘\Sample\ch07\素材\SQLHelper.txt)。
提示
SQLHelper类是广大程序员智慧的结晶,SQLHelper类功能的完善离不开广大使用者的修改、补充。以后大家在使用过程中发现SQLHelper类的哪些功能需要修改或补充,一定要公开你的源代码,否则SQLHelper类的功能就不能完善,技术就会停滞不前。
9.4 ASP.NET数据控件
本节视频教学录像:14分钟
本节介绍ASP.NET 4.0中数据控件的应用。
9.4.1 数据访问控件概述
在 ASP.NET 4.0 中可以看到以下几种数据控件:DataList、Repeater、GridView、ListView、DetailsView、FormView。这几种控件的区别如下。
⑴DataList、Repeater、GridView、ListView、DynamicControl 用于呈现多条记录;DetailsView、FormView用于呈现单条数据明细,即常用的记录明细。
⑵GridView和DetailsView控件的布局固定,自定义数据显示的布局功能有限,一般适合布局简单的数据呈现。
⑶DataList、Repeater和FormView数据控件都有很强的自定义布局能力,如果数据呈现需要较为复杂的布局方案,这3个控件是首选。
⑷GridView 、DetailsView和FormView等3个都是从.net 2.0新增的控件,内置了分页、排序等功能,同时支持多个主键字段提供了一些接口供用户自定义UI(如关联主题、皮肤、样式表等)。
⑸DataList和Repeater是从1.1版就提供的控件,内置功能较弱,需要自己实现分页、排序、数据事件等功能。
⑹在现在的Asp.net平台上,如果从功能上来说,呈现单列数据时DetailsView和FormView相对应,DetailsView布局固定,FormView自定义布局。呈现多列数据时只有GridView来负责布局固定的数据。从功能上来说没有对应的控件与GridView相配。
⑺DataList提供的数据功能与GridView相比,相对少了一些。与GridView几乎不需要编程就能担负数据呈现的重任相比,DataList要求程序员必须自己写代码来实现想要的功能。
下面逐一讲解各个控件的用法。
9.4.2 GridView控件
本节通过一个实例学习使用GridView控件,本例使用的是Student数据库中Studentinfo数据表。该例的功能是用GridView控件显示student数据库中information数据表中的数据。
工作流程如下:
⑴用GridView控件显示数据;
⑵自定义GridView控件的外观;
⑶定制列元素;
⑷排序;
⑸分页浏览。
【范例9-8】GridView控件综合应用。
1. 使用GridView控件显示数据
⑴新建一个名为GridView的Asp.net空网站,添加一个名为GridView.aspx的页面。
⑵添加一个SQLDataSource控件,修改其ID为SqlStudentDataSource。通过配置数据源,连接数据库服务器并选择要访问的数据库。
⑶单击【确定】按钮返回配置界面,单击【下一步】按钮,提示是否保将连接字符串保存到配置文件中,单击【下一步】按钮,打开【配置select语句】界面。选择要检索的数据表。
此处【where】可以设置筛选条件;【ORDER BY】可以设置按照哪个字段进行排序;【高级】可以配置高级选项,单击后打开【高级SQL生成选项】,选中【生成INSERT、UPDATE和DELETE语句】。
⑷单击【下一步】按钮,打开【测试查询】界面,直接单击【完成】按钮即可。
⑸从工具箱添加一个GridView控件到页面,在弹出的【GridView任务】小窗口中将刚才配置的SqlStudentDataSource作为GridView控件的数据源。配置后GridView控件如图所示。
【运行结果】
按【F5】键运行,测试运行结果,如图所示。
2. 自定义GridView控件外观
上图中GridView的外观比较简单,如果想格式化GridView,要设置GridView的相关属性。最简单的方法是使用“自动套用格式”。
⑴在GridView.aspx的“设计”视图中,选中GridView控件,单击打开【GridView任务】面板。
⑵单击【自动套用格式】,在弹出的【自动套用格式】窗口中选择一种方案,比如“专业型”。单击【确定】按钮。
【运行结果】
按【F5】键运行,测试运行结果,如图所示。
3. 定制列元素
通过上面的运行结果我们可以看到,控件的列标题默认采用数据表的字段名称,可读性差,如果要自定义列标题以及要显示的内容,需要设置相应的属性。
⑴在GridView.aspx的“设计”视图中,选中GridView控件,点击打开【GridView任务】面板。
⑵单击【编辑列】,打开“字段”窗口。【可用字段(A)】是数据表中的字段信息;【选定的字段(S)】是GridView控件中绑定的字段。
⑶单击【选定的字段(S)】中的某个字段,可以打开该绑定字段的属性窗口。比如,为了增加可读性,可以通过修改HeaderText属性,将学号字段的“NO”改为“学号”。
BindField列常用属性如下表所示。
⑷用同样的方法,将其他字段改为相应的中文名称。
⑸选中某个字段,单击按钮,分别可以实现调整列的显示顺序和删除某个列的作用,单击【确定】按钮。
【运行结果】
按【F5】键运行,测试运行结果,如图所示。从图中我们可以看到,所有的列标题都改成了中文,增加了可读性,同时删除了【生日】列。
4. 分页、排序、数据修改等高级应用
⑴在GridView.aspx的“设计”视图中,选中GridView控件,单击打开【GridView任务】面板。
⑵选中【启用排序】、【启用编辑】、【启用删除】。即可实现点击标题文本进行排序,同时添加编辑按钮列和删除按钮列。轻松实现对该行数据的修改和删除。
⑶选中【启动分页】即可使GridView控件每页显示10条数据。我们可以通过设置GridView控件的PageSize属性设置每页显示的数据行数。
【运行结果】
按【F5】键运行,测试运行结果,如图所示。
5. 超级链接列
如果我们希望通过单击某个学生的姓名来查看某一个学生的详细内容,则需要将学生姓名列设为“超级链接列”。
⑴在GridView.aspx的“设计”视图中,选中GridView控件,点击打开【GridView任务】面板。点击【添加新列】,打开“添加字段”窗口。
⑵在“页眉文本”中输入:“姓名”;列标题显示文本信息。在“超链接文本”中选择“从数据字段获取文本”:选择SName,说明超链接的文本是从数据表字段获取的。在“超链接URL”中选择“从数据字段获取URL”:选择NO,此处用来判断点击了哪条记录,一般此处选择数据表额主键。在“URL格式字符串”输入:“StuDetail.aspx?id={0}”,是用来说明点击超链接要导向的页面以及向页面传递的参数值。单击【确定】按钮。如图所示。
⑶选中第一个姓名列,点击打开【GridView任务】面板。点击【移除列】,删除该列。
⑷选中超级链接的姓名列,点击打开【GridView任务】面板。多次点击【左移列】,可以将该列移动到左侧,如图所示。
运行并浏览GridView.aspx页面,如图所示。
可以看到,姓名一列变成了超链接,但是单击会出现HTTP 404错误,原因是超链接是要链接到StuDetail.aspx页面,但是这个页面我们还没有添加。下面创建StuDetail.aspx页面。
⑸添加一个名为StuDetail.aspx的页面,切换到设计视图并添加一个GridView控件。
⑹单击打开【GridView任务】面板。如图所示,选择【新建数据源】。
⑺在打开的界面选择SQL数据库,单击【确定】按钮,在弹出的窗口中通过下拉箭头选择使用的链接,单击【下一步】按钮打开【配置select语句】窗口,在“希望如何从数据表中检索数据”中选择StudentInfo表。
⑻单击【where(w)…】,打开“添加where子句”窗口,配置如图所示。最后单击【添加】按钮。
⑼单击【确定】按钮,然后直接单击【下一步】按钮直至【完成】。
将GridView.aspx页面设置为起始页,按【F5】键运行,点击某个学生的姓名,即可打开StuDetail.aspx页面,并查看到该学生的详细信息。
【范例分析】
本例我们通过GridView控件和SqlDataSource控件的绑定来显示、编辑数据。这种通过SqlDataSource访问数据的方式的确给我们带来了很大的方便,很适合初学者,但是不够灵活,有些高级应用还需要借助于程序编码来实现。
【范例9-9】GridView控件通过程序代码实现的高级应用。
1. 使用GridView控件显示数据
⑴新建一个名为GridViewGaoji的Asp.net空网站,添加一个Default.aspx页面并切换到设计视图。
⑵从【工具箱】中添加一个GridView控件,修改ID为gvStudent。
⑶双击页面或者按【F7】键切换到Defaut.aspx.cs页面,添加需要引入的命名空间和变量,代码如下:
using System.Data.SqlClient;
using System.Data;
//添加类一级字段,即页面级变量
string ConnStr ="server=.\\sqlexpress; Integrated Security=SSPI;database=Student";
⑷添加gvBind()方法,用于将数据绑定到GridView控件(代码9-9.txt)。
01 protected void gvBind()
02 {
03 SqlConnection conn= new SqlConnection(ConnStr);
04 SqlCommand cmd= new SqlCommand();
05 cmd.Connection= conn;
06 cmd.CommandText= "Select * from StudentInfo";
07 try
08 {
09 conn.Open();
10 SqlDataAdapter ada= new SqlDataAdapter(cmd);
11 DataSet ds= new DataSet();
12 ada.Fill(ds, "student");
13 this.gvStudent.DataSource=ds.Tables[0].DefaultView;
14 this.gvStudent.DataBind();
15 }
16 catch (SqlException sex)
17 {
18 throw sex;
19 }
20 finally
21 {
22 if (conn.State==ConnectionState.Open)
23 {
24 conn.Close();
25 }
26 }
27 }
⑸在Page_Load()事件中添加对gvBind方法的调用。
至此,实现对Studentinfo数据表的访问,按【Ctrl+F5】组合键运行即可看到运行结果。
然后参照【范例9-8】中的自定义GridView控件外观和定制列元素可以实现对GridView控件外观的调整和数据绑定的显示。此处不再说明。设置后如图所示。
2. 实现对GridView的分页操作
⑴选中gvStudent控件,调出【属性】窗口,设置“AllowPaging”为【True】;“PageSize”属性默认为10,代表一页有10行数据,因为数据库中数据较少,所以设置为3,这样就可以显示分页。
⑵选中gvStudent控件,调出【属性】窗口,切换到【事件】面板,如图所示。
⑶在PageIndexChanging事件中双击,打开页面的cs代码,在gvStudent_PageIndexChanging()事件中输入以下代码:
01 protected void gvStudent_PageIndexChanging(object sender,GridViewPageEventArgs e)
02 {
03 gvStudent.PageIndex= e.NewPageIndex;
04 gvBind();
05 }
【运行结果】
按【Ctrl+F5】组合键运行,运行结果如图所示,点击页面数字即可实现换页。
3. 实现对GridView控件的排序操作
GridView控件一个重要的特性是排序功能。要实现排序功能,需将GridView控件的AllowSorting属性设置为True,并在其Sorting事件处理程序中编写代码。
当排序功能启动时,可排序的数据列的标题将显示为“可点击”的链接,用户可以通过单击标题将网格中的数据列进行排序。
⑴选中gvStudent控件,调出【属性】窗口,设置“AllowSorting”为【True】,启用分页操作。
⑵选中gvStudent控件,点击小箭头调出【GridView任务】面板,点击【编辑列】,选中需要作为排序的字段,此处选中【学号】。如图所示。
⑶设置右侧的SortExpression为学号对应的数据库字段名称“no”。
⑷选中gvStudent控件,调出【属性】窗口,切换到【事件】面板,双击sorting事件,打开页面的cs代码页面。
⑸在gvStudent_Sorting()事件中输入以下代码:
01 protected void gvStudent_Sorting(object sender,GridViewSortEventArgs e)
02 {
03 string sPage= e.SortExpression;
04 if (ViewState["SortOrder"].ToString()== sPage)
05 {
06 if (ViewState["OrderDire"].ToString()== "Desc")
07 ViewState["OrderDire"]= "ASC";
08 else
09 ViewState["OrderDire"]= "Desc";
10 }
11 else
12 {
13 ViewState["SortOrder"]= e.SortExpression;
14 }
15 gvBind();
16 }
⑹修改gvBind()方法代码为:
01 protected void gvBind()
02 {
03 SqlConnection conn= new SqlConnection(ConnStr);
04 SqlCommand cmd= new SqlCommand();
05 cmd.Connection= conn;
06 cmd.CommandText= "Select * from StudentInfo";
07 try
08 {
09 conn.Open();
10 SqlDataAdapter ada= new SqlDataAdapter(cmd);
11 DataSet ds= new DataSet();
12 ada.Fill(ds, "student");
13 DataView view=ds.Tables[0].DefaultView;
14 string sort= (string)ViewState["SortOrder"]+ " "+ (string)ViewState["OrderDire"];
15 view.Sort= sort;
16 this.gvStudent.DataSource= view;
17 this.gvStudent.DataBind();
18 }
19 catch (SqlException sex)
20 {
21 throw sex;
22 }
23 finally
24 {
25 if (conn.State==ConnectionState.Open)
26 {
27 conn.Close();
28 }
29 }
30 }
⑺修改Page_Load()代码为:
01 protected void Page_Load(object sender,EventArgs e)
02 {
03 if (!IsPostBack)
04 {
05 ViewState["SortOrder"]= "no";
06 ViewState["OrderDire"]= "ASC";
07 gvBind();
08 }
09 }
【运行结果】
按【F5】键运行,测试运行结果,学号字段标题变成超链接样式,点击即可实现按学号排序,如图所示。
【范例分析】
要想对GridView控件进行排序,需要设置allowsorting为True,同时需要设置按哪个字段进行排序,即设置SortExpression属性。使用ViewState来保存排序的字段和排序方式。步骤⑹的13~16行实现的是根据ViewState["SortDirection"]的值生成排序后的DataView对象作为GridView控件的数据源。
4. 实现对GridView控件录入、更新、删除等操作
GridView 控件可以允许用户就地编辑网格行中的信息。为此,需要创建“编辑”、“更新”、“取消”列,并向 GridView 的 EditCommand、UpdateCommand 和 CancelCommand 事件添加代码。在运行时,此列显示一个标记为“编辑”的按钮。当用户单击此“编辑”按钮时,行数据在如文本框等的可编辑控件中显示,“编辑”按钮被替换为“更新”和“取消”按钮。单击“更新”按钮引发UpdateCommand 事件,在该事件中添加代码以将数据更改传播回数据源。单击“取消”按钮引发CancelCommand 事件,在该事件中添加代码以将原始数据重新绑定到 GridView。
为了允许对行进行编辑,GridView 支持整型 EditItemIndex 属性,该属性指示网格的哪一行应该是可编辑的。设置了该属性后,GridView 按该索引将行呈现为文本输入框。值“-1”(默认值)指示没有行是可编辑的。
将GridView的DataKeyField属性设为数据表中主键字段名,从而在UpdateCommand 事件处理程序中可以从GridView的DataKeys集合检索键名,方法为GridView1.DataKeys[e.Item.ItemIndex]。
在 GridView 上,将事件处理程序连接到 DeleteCommand,并从那里执行删除操作。同样使用DataKeys 集合确定客户端选择的行。
录入操作步骤如下:
⑴打开Default.aspx页面的设计视图,在页面原有基础上添加6个文本框和一个按钮,如图所示。
⑵修改控件属性,同时修改gvStudent控件的DataKeyNames属性为“no”,用来指明数据源中的键值字段。如下表所示。
⑶双击【录入数据】按钮,打开cs页面的btnInsert_Click()事件,输入以下代码,即可实现通过文本框向数据表录入数据。
01 protected void btnInsert_Click(object sender,EventArgs e)
02 {
03 string insertStr= "INSERT studentinfo VALUES ('"+ txtSno.Text+ "','"+ txtSname.Text+ "','"+ txtSex.Text+ "','"
04 + txtBirthday.Text+ "','"+ txtCno.Text+ "','"+ txtScore.Text+ "','"+ ""+ "')";
05 SqlConnection conn= new SqlConnection(ConnStr);
06 SqlCommand cmd= new SqlCommand(insertStr,conn);
07 try
08 {
09 conn.Open();
10 cmd.ExecuteNonQuery();
11 Response.Write("<script>alert('录入成功 ')< /script>");
12 }
13 catch
14 {
15 Response.Write("<script>alert('录入失败 ')< /script>");
16 }
17 finally
18 {
19 conn.Close();
20 }
21 gvBind();
22 }
⑷选中gvStudent控件,点击小箭头调出【GridView任务】面板,打开【字段】窗口,在可用字段处将CommandField前面的加号点开,如图所示。
⑸分别选中【编辑、更新、取消】和【删除】,点击【添加】按钮,然后点击【确定】按钮。添加后的GridView控件如图所示,增加了编辑和删除。
⑹要想实现对数据的编辑和删除,需要添加相应的事件代码才能实现。选中gvStudent控件,调出【属性】窗口,切换到【事件】面板,双击RowEditing事件,打开cs代码页面。输入以下代码:
01 protected void gvStudent_RowEditing(object sender,GridViewEditEventArgs e)
02 {
03 gvStudent.EditIndex= e.NewEditIndex;
04 gvBind();
05 }
⑺重复步骤⑹ ,双击RowUpdating事件,输入以下代码:
01 protected void gvStudent_RowUpdating(object sender,GridViewUpdateEventArgs e)
02 {
03 string updateStr= "";
04 updateStr+="no='"+ ((TextBox)gvStudent.Rows[e.RowIndex].Cells[0].Controls[0]).Text+ "'";
05 updateStr+=",sname='"+ ((TextBox)gvStudent.Rows[e.RowIndex].Cells[1].Controls[0]).Text+ "'";
06 updateStr+=",sex='"+ ((TextBox)gvStudent.Rows[e.RowIndex].Cells[2].Controls[0]).Text+ "'";
07 updateStr +=",birthday='" +((TextBox)gvStudent.Rows[e.RowIndex].Cells[3].Controls[0]).Text +"'";
08 updateStr+=",cno='"+ ((TextBox)gvStudent.Rows[e.RowIndex].Cells[4].Controls[0]).Text+ "'";
09 updateStr+=",score='"+ ((TextBox)gvStudent.Rows[e.RowIndex].Cells[5].Controls[0]).Text+ "'";
10 string updateCmd= "UPDATE studentinfo SET "+ updateStr+ "WHERE no= '"+ gvSt11 udent.DataKeys[e.RowIndex].Value.ToString()+ "'";
12 SqlConnection conn= new SqlConnection(ConnStr);
13 SqlCommand myCommand= new SqlCommand(updateCmd,conn);
14 try
15 {
16 conn.Open();
17 myCommand.ExecuteNonQuery();
18 gvStudent.EditIndex= -1;
19 }
20 catch
21 {
22 Response.Write("<script>alert('更新失败! ')< /script>");
23 }
24 finally
25 {
26 conn.Close();
27 }
28 gvBind();
29 }
⑻重复步骤⑹ ,双击RowCancelingEdit事件,输入以下代码:
01 protected void gvStudent_RowCancelingEdit(object sender,GridViewCancelEditEventArgs e)
02 {
03 gvStudent.EditIndex= -1;
04 gvBind();
05 }
⑼重复步骤⑹ ,双击RowDelting事件,输入以下代码:
01 protected void gvStudent_RowDeleting(object sender,GridViewDeleteEventArgs e)
02 {
03 string delCmd = "DELETE FROM studentinfo WHERE no = '"+ gvSt04 udent.DataKeys[e.RowIndex].Value.ToString()+ "'";
05 SqlConnection conn= new SqlConnection(ConnStr);
06 SqlCommand myCommand= new SqlCommand(delCmd, conn);
07 try
08 {
09 conn.Open();
10 myCommand.ExecuteNonQuery();
11 }
12 catch
13 {
14 Response.Write("<script>alert('删除失败! ')< /script>");
15 }
16 finally
17 {
18 conn.Close();
19 }
20 gvBind();
21 }
【运行结果】
按【F5】键运行,测试运行结果,至此,可以实现对数据的录入、修改、删除操作。
【范例分析】
GridView控件的DataKeyNames属性用来指明数据源的键值字段,这个属性非常重要,在对数据进行更新或删除操作时都需要使用它,gvStudent.DataKeys[e.RowIndex].Value.ToString()即是对它的引用。
Row_Editing事件中的gvStudent.EditIndex = e.NewEditIndex语句是指明GridView控件中的哪一行作为编辑行;gvStudent.EditIndex=-1是指明取消编辑模式,回到浏览模式。
当GridView控件变成编辑模式后,我们会发现单元格中变成了文本框,gvStudent.Rows[e. RowIndex].Cells[0].Controls[0]的作用就是获取gvStudent控件RowIndex行的第0个单元格中的第0个控件,但是这个返回的是对象类型,因此加上(TextBox)进行强制类型转换,然后获取内容信息。
9.4.3 DetailsView控件
上一节介绍的GridView控件主要是以表格的形式一次呈现大量数据。但是,有些情况下仅仅需要呈现一条数据,例如在主\从方式的应用程序中。这时,我们就可以借助DetailsView控件来完成这个功能。使用DetailsView控件可以在表格中显示来自数据源的单条记录的值,其中每个数据行表示该记录的一个字段,表格只包含两列,一列显示字段名,另一列则显示字段值。
DetailsView 控件支持以下一些功能。
⑴绑定至数据源控件,如 SqlDataSource。
⑵内置插入功能。
⑶内置更新和删除功能。
⑷内置分页功能。
⑸以编程方式访问 DetailsView 对象模型,以动态设置属性、处理事件等。
⑹可通过主题和样式自定义外观。
【范例9-10】DetailsView控件分页显示数据。
⑴新建一个名为DetailsView的Asp.net空网站,然后在项目名称上单击右键,选择【添加新项】【web窗体】,添加一个页面,默认为Default.aspx。
⑵打开页面的设计视图,添加一个DetailsView控件和一个SqlDataSource控件。通过配置数据源,连接数据库服务器并选择要访问的数据库Student及要访问的数据表StudentInfo。如图所示(不选Picture)。
⑶点击【高级】按钮,在【高级SQL生成选项】窗口选中【生成INSERT、UPDATE和DELETE语句】。
⑷设置DetailsView1的数据源为SqlDAtaSource1,同时选中启用分页、启用插入、启用编辑和启用删除。
⑸给DetailsView自动套用一种格式,本处选择【专业型】。
【运行结果】
按【Ctrl+F5】组合键运行,测试运行结果,如图所示。单击【编辑】可以实现对数据的编辑,单击【删除】可以实现对数据的删除,单击【新建】可以实现录入一条记录。
DetailsView 控件与 GridView 控件形成了很好的互补。将 DetailsView 连接到 GridView 可以更好地控制更新个别项目或插入新项目的方式和时机。
9.4.4 FormView控件的属性
与 DetailsView 控件一样,FormView 通过其关联的数据源控件支持自动 Update、Insert 和 Delete 等操作。若要定义编辑或插入操作的输入 UI,可在定义 ItemTemplate 的同时定义 EditItemTemplate 或InsertItemTemplate。在本模板中,您可以对输入控件(如 TextBox、CheckBox 或 DropDownList)进行数据绑定,以绑定到数据源的字段。但是,这些模板中的数据绑定使用双向数据绑定语法,从而允许FormView 从模板中提取输入控件的值,以便传递到数据源。这些数据绑定使用新的 Bind(fieldname) 语法,而不是 Eval。
提示
使用.Bind.语法进行数据绑定的控件必须设置有.ID.属性。
FormView 支持使用 DefaultMode 属性指定要显示的默认模板,但在默认情况下,FormView 以ReadOnly 模式启动并呈现 ItemTemplate。若要启用用于从 ReadOnly 模式转换为 Edit 或 Insert 模式的UI,可以向模板中添加一个 Button 控件,并将其 CommandName 属性设置为 Edit 或 New。我们可以在 EditItemTemplate 内添加 CommandName,设置为 Update 或 Cancel 的按钮,以用于提交或中止更新操作。类似的,也可以添加 CommandName,设置为 Insert 或 Cancel 的按钮,以用于提交或中止插入操作。源代码如下。
01 <asp:FormView DataSourceID="ObjectDataSource1"DataKeyNames="PhotoID" runat="server">
02 <EditItemTemplate>
03 <asp:TextBox ID="CaptionTextBox" Text='<%#Bind("Caption")%>' runat="server"/>
04 <asp:Button Text="Update"CommandName="Update" runat="server"/>
05 <asp:Button Text="Cancel"CommandName="Cancel" runat="server"/>
06 < /EditItemTemplate>
07 <ItemTemplate>
08 <asp:Label Text='<%#Eval("Caption")%>' runat="server" />
09 <asp:Button Text="Edit"CommandName="Edit" runat="server"/>
10 < /ItemTemplate>
11 < /asp:FormView>
9.4.5 FormView控件的操作
FormView和DetailsView控件很相似。该控件同样是绑定数据源中的一条记录。两者的区别在于DetailsView控件使用预定义的表格布局,而FormView控件没有指定显示记录的布局方式。正是FormView控件的这种特征拥有很强的自定义功能,因此可以创建一个包含控件的模板,以显示记录中的各个字段。
【范例9-11】FormView控件的使用。
第一步:实现数据的绑定
⑴新建一个名为FormView的Asp.net空网站,然后在项目名称上单击右键,选择【添加新项】【web窗体】命令,添加一个页面,默认为Default.aspx。
⑵打开页面的设计视图,添加一个FormView控件和一个SqlDataSource控件。通过配置数据源,连接数据库服务器并选择要访问的数据库Student及要访问的数据表StudentInfo(查询时不选Picture)。同时在【高级SQL生成选项】窗口选中【生成INSERT、UPDATE和DELETE语句】。
⑶设置FormView控件的数据源为SqlDAtaSource1,同时选中启用分页。
⑷在【FormView任务】面板上单击【编辑模板】并从【显示】框中选择【ItemTemplate】,进入ItemTemplate模板编辑模式后将英文标签改为中文,如图所示。
⑸再从【FormView任务】面板的【显示】框中选择【HeaderTemplate】,输入【学生信息】。
⑹完成模板编辑后,在【FormView任务】面板中点击【结束模板编辑】链接。
【运行结果】
按【Ctrl+F5】组合键运行,测试运行结果,如图所示。
第二步:给【删除】添加上【确认】对话框
⑴选中FormView控件,调出【属性】窗口,切换到【事件】面板,双击ItemCreated事件,在打开的cs页面的FormView1_ItemCreated事件中输入下面的代码:
01 protected void FormView1_ItemCreated(object sender,EventArgs e)
02 {
03 ((LinkButton)FormView1.Row.FindControl("DeleteButton")).Attributes.Add("onClick", "return confirm('确定要删除么 ');");
04 }
【运行结果】
按【Ctrl+F5】组合键运行,点击【删除】按钮会出现确认对话框,如图所示。
【范例分析】
同GridView控件访问内容控件一样,FormView1.Row.FindControl("DeleteButton")的作用是找到FormView控件当前行中ID为DeleteButton的控件,并强制转换为LinkButton类型,并为其添加一个属性。
9.4.6 ListView控件和DataPager控件
ListView控件和DataPager控件相结合,可以实现分页显示数据的功能。ListView控件用于显示数据,提供了编辑、删除、插入、分页等功能,分页功能是通过DataPager控件来实现的。DataPager控件的PagedControlID属性用来指定进行分页的ListView控件的ID。
【范例9-12】ListView控件和DataPager控件的使用。
⑴新建一个名为ListViewDataPager的Asp.net空网站,然后在项目名称上单击右键,选择【添加新项】【web窗体】命令,添加一个页面,默认为Default.aspx。
⑵打开页面的设计视图,添加一个 ListView 控件和一个 SqlDataSource 控件。通过配置数据源,连接数据库服务器并选择要访问的数据库Student及要访问的数据表StudentInfo(查询时不选Picture)。同时在【高级SQL生成选项】窗口选中【生成INSERT、UPDATE和DELETE语句】。
⑶设置ListView控件的数据源为SqlDAtaSource1。
⑷在【ListView任务】面板上单击【配置ListView】,选择相应的布局方式和样式,启用编辑、删除和插入(不选择启用分页),如图所示。
⑸添加一个 DataPager 控件到页面中,设置 DataPager 控件的 PagedControlID 为 ListView1, PageSize属性设置为3。
【运行结果】
按【Ctrl+F5】组合键运行,测试运行结果,如图所示。
9.5 高手点拨
本节视频教学录像:3分钟
1. GridView控件中的RowType
RowType可以确定GridView中行的类型,RowType是枚举变量DataControlRowType中的一个值。RowType 的取值可以包括 DataRow、Footer、Header、EmptyDataRow、Pager、Separator。很多时候,我们需要判断当前是否是数据行,通过如下代码来进行判断:if (e.Row.RowType ==DataControlRowType.DataRow),比如要实现鼠标放到数据行上高亮显示,就需要使用这个判断。
2. ADO.NET中的事务控制
事务可以确保多个SQL语句被当作单个工作单元来处理,保证了数据的一致性和可恢复性。在 ADO.NET 中,可以使用 Connection 和 Transaction 对象来控制事务。调用 Connection 对象的BeginTransaction 方法来标记事务的开始。调用Transaction 对象的Commit 方法来完成事务,或调用Rollback 方法来取消事务。
9.6 实战练习
1. 使用SQL Server2008创建一个名称为Person的数据库,并在其中定义一个名称为PersonelInfo的表,表的结构如下。
向表中添加5~10条记录。然后创建一个ASP.NET Web应用程序,编写代码,使用GridView控件显示表中所有年龄大于18岁的记录,并且显示时要按编号升序排序。
2. 选中某行后,使用DetailsView控件显示该行的详细信息。