第7章 SQL Server数据库应用程序开发

7.1. 客户基本信息管理示例
本节给出的示例是客户信息维护的程序实现,程序实现了查询、添加和删除客户信息的功能。程序界面如下,
图 7 1 合同管理系统客户维护模块功能界面
在图 7 1中,窗口下部的客户信息列表是自动显示的。“插入”按钮负责将新输入的客户信息插入到数据库中并在客户信息列表中显示,“删除”按钮删除客户信息列表中当前行。
7.1.1. 准备数据库环境
下面的过程在利用AdventureWorks示例数据库创建一个简单的数据库Example,它有Customer和SalesOrderHeader两个表,它们分别是AventureWorks数据库中Salses.Customer和Sales.SalesOrderDetail表的简化版本。
创建Example数据库的操作如下:
(1) 创建Example数据库。
(2) 运行下面的代码在Example数据库中创建表Customer和SalesOrderHeader。
USE Example
GO

SELECT C.CustomerID,P.LastName,P.FirstName,C.AccountNumber
INTO Customer
FROM AdventureWorks.Person.Person P INNER JOIN
AdventureWorks.Sales.Customer C
ON C.PersonID=P.BusinessEntityID;
GO

ALTER TABLE Customer ADD CONSTRAINT
PK_Customer PRIMARY KEY CLUSTERED
(
CustomerID
)

GO

SELECT SalesOrderID,CustomerID,OrderDate,DueDate,ShipDate
into SalesOrderHeader
FROM AdventureWorks.Sales.SalesOrderHeader
GO

ALTER TABLE SalesOrderHeader ADD CONSTRAINT
PK_SalesOrderHeader PRIMARY KEY CLUSTERED
(
SalesOrderID
)
GO

ALTER TABLE SalesOrderHeader ADD CONSTRAINT
FK_SalesOrderHeader_Customer FOREIGN KEY
(CustomerID) REFERENCES Customer(CustomerID)
GO

7.1.2. 创建项目和窗体

(1) 创建项目
打开Visual Studio,选择“文件/新建/项目”菜单创建项目,进入VisualStudio.NET的“新建项目”对话框(图 7 2),在“新建项目”对话框中选择项目类型为“Visual C#项目”,模板为“Windows应用程序”,设置项目的名称为“客户管理”,项目所在的路径为“C:\”,程序会将创建的项目存储在“C:\客户管理”目录下,最后点击“确定”按钮完成项目的创建。
图 7 2 创建客户管理项目
这时会在Visual Studio中出现如图 7 3所示的结果。
(2) 修改窗体的标题。
选择Form1窗体,在右下角的属性窗口中修改Form1的Text属性为“客户管理”,结果Form1窗体的标题显示为“客户管理”。如果选择Form1后没有出现属性窗口,可以通过右键弹出菜单显示属性窗口。
(3) 添加控件
如果工具箱面板没有出现,可以通过“视图/工具箱”菜单显示“工具箱”面板。在“工具箱”面板的“Windows窗体”分类中选择“Label”,然后在Form1窗体放置“客户编号”的位置点击,窗体上会出现一个“label1”的控件,修改“属性”窗口中label1的Text属为的值为“客户编号”。
再选择“工具箱”面板中的文本框控件TextBox,然后在窗体上放置客户编号的文本框的位置点击,窗体上会出现一个textBox1的文本框,修改该文本框的Name属性为tbxCustomerID,Text属性的值清空。
完成后的结果窗体如图 7 4所示,
图 7 3 新创建的客户管理项目
图 7 4 添加客户编号文本框后的窗体

其它的文本和文本框的添加方法与客户编号相似。
显示客户信息列表的是数据网格控件DataGrid,将它放置在所有输入信息控件的下方,最后放置按钮控件“插入”、“删除”和“关闭”完成控件的添加。
注释:如果Visual Studio的工具箱/数据分支中没有出现DataGrid,则可以使用弹出菜单的“选择项…”从.NET Framework组件中添加DataGrid控件。
(4) 布置控件
你可以使用“格式”菜单来调整控件的大小和位置。修改数据网格控件的锚接属性Anchor为“Top,Bottom,Left,Right”,这样,在运行的过程中数据网格与其它控件的相对位置不会随着窗体的大小变化而变化(通过自动调整其大小来调整相对位置),将三个按钮的Anchor属性修改为“Bottom,Right”,这样,它们相对于窗体右下角的位置不会发生变化。
此时,运行程序后看不到客户信息的内容,因为你还没有为程序添加访问数据库的内容。
7.1.3. 查询功能的实现
注释:Visual Studio 2012中介绍的主要方法为使用BindingSource与TableAdapter等组件,使用这种方法需要编写的代码更少,但其缺点是很多过程无法编写代码加以控制,只能通过设计器完成,也难以掌握ADO.NET数据访问的相关概念和方法,因此,本示例中所使用的数据绑定方法为较早版本中的方法。
1. 创建数据连接和数据适配器
(1) 从“工具箱”的“数据”选项卡中,将 OleDbDataAdapter 对象拖到窗体上。
“数据适配器配置向导”启动,它将创建连接和适配器。
注释:如果Visual Studio的工具箱/数据分支中没有出现OleDbDataAdapter,则可以使用弹出菜单的“选择项…”从.NET Framework组件中添加OleDbDataAdapter组件。
(2) 在该向导中,执行下列操作:
 在第二个窗格中,创建或选择一个指向 Example数据库的连接。
 在第三个窗格中,指定使用 SQL 语句来访问数据库。
 在第四个窗格中创建以下 SQL 语句:
图 7 5 客户信息的查询语句
为了便于生成 SQL 语句,请单击“查询生成器”以启动“查询生成器”。
(3) 单击“完成”完成该向导。
向导完成后,将获得一个连接oleDbConnection1,该连接包含与如何访问数据库有关的信息。数据适配器oleDbDataAdapter1和oleDbConnect连接对象将添加到组件窗口中。
每个数据适配器对象有DeleteCommand、InsertCommand、UpdateCommand和SelectCommand四个命令对象属性,命令对象有连接对象属性Connection和CommaneText命令文本属性。oleDbDataAdapter1.SelectCommand.Connection的值为oleDbConnection1,oleDbDataAdapter1.SelectCommand.CommandText为上面的查询语句。这些属性的值都是使用设计器生成的,你可以手工修改这些内容。
注释:.NET组件是实现了IComponent接口的类的实例,而控件是拥有用户界面的组件。
2. 生成数据集
(1) 在组件窗口选择数据适配器对象oleDbDataAdapter1生成数据集(可以从弹出菜单、智能编辑、属性窗口中选择“生成数据集”)。
显示“生成数据集”对话框。
(2) 选择“新建”选项,将数据集命名为 dataSet1。
在“选择要添加到数据集中的表”下面的列表中,应选择“Customer”表。
(3) 确保“将此数据集添加到设计器”已选中,然后单击“确定”。
最后,Visual Studio 将新数据集的一个实例dataSet11添加到窗体中。
此时,已完成为从数据库中获取信息并将信息转移到数据集所需的全部设置。准备创建一个显示数据的窗体。
3. 绑定数据到数据网格
(1) 在客户信息列表数据网格控件dataGrid1的DataSource 属性中,选择 dataSet11作为数据源。不选择 dataSet11.Customer。 如果是从DataSource属性的下拉列表框中选择,则展开“其它数据库源”并选择“列表实例”节点下面的数据库集dataSet11而不选择“项目数据源”下的数据集dataSet11。
(2) 在 DataMember 属性中选择“Customer”。设置这两个属性会将 dataSet11数据集内的 Customer数据表绑定到网格。
(3) 调整网格的大小,以便可以看到所有列。更改其高度,以便能够看到多个客户记录。
4. 填充DataGrid控件
(1) 双击该窗体(空白处)以创建其 Load 事件的事件处理程序Form1_Load。
(2) 在该方法中,然后调用数据适配器的 Fill 方法,向该方法传递要填充的数据集。
下面的示例显示完整的方法:
图 7 6 窗体的Load事件处理方法
窗体的Load事件是窗体第一次显示时触发的事件,对于设计器来说,它是窗体的默认事件。按钮的默认事件是Click。在设计器中,双击一个控件会自动生成该控件的默认事件处理方法,如果方法已经存在,则双击会打开事件处理方法的代码。
事件处理方法Form1_Load中只有一条语句,该语句的功能是调用数据适配器oleDbAdapter1的Fill方法填充数据集dataSet11。它会导致使用数据连接对象oleDbConnection1连接数据库并执行数据适配器中的SELECT语句,最后将查询结果写到数据集中。
数据适配器的Fill()方法的执行流程如下:
 如果SELECT命令对象的连接还没有打开,则打开相应的连接;
 将SELECT SQL命令发送给数据库服务器执行;
 服务器将查询结果返回数据适配器,如果命令无法执行则抛出异常;
 数据适配器将查询结果填充到指定的数据集dataSet11的数据表Customer;
 如果SELECT命令对象的连接是在执行Fill ()方法时执行了打开操作,关闭相应的连接;
 Fill()方法执行完毕。
注释:当数据集dataSet11中的内容发生变化时,绑定的数据控件dataGrid1会收到数据集中内容发生变化的事件,并使用新的内容填充数据控件。这个任务与数据适配器无关。
(3) 运行程序,可以看到如图 7 1所示的结果。
7.1.4. 添加功能的实现
(1) 双击“插入”按钮,Visual Studio会自动生成该控件的Click事件的处理程序btnInsert_Click,其中btnInsert是控件的名称。
(2) 在事件处理程序btnInsert_Click中输入相应的内容,完整的处理程序如下,
方法一:使用命令对象完成插入操作

图 7 7 插入按钮的Click事件处理程序
在程序中首先构造一个插入命令,该命令负责插入记录到Customer表中,它有4个参数,使用一个字符串对象strCustomerInsert存储该命令。需要注意的是,前面添加的数据连接对象使用的是OLEDB数据提供程序,因此,这里构造一个OLEDB数据提供程序的命令对象cmdCustomerInsert,构造函数的参数是插入命令语句的文本,最后将命令对象的Connection属性设置成oleDbConnection1数据连接对象,这样就完成了该命令对象的构造。
也可以不使用参数而直接将获得的值加入到插入命令的文本中,后面的删除操作演示了不使用参数的方法。
接下来的语句是创建命令对象的参数,它使用了命令对象参数集合Parameters的Add方法添加参数。Add方法的三个参数分别是参数的名称、参数的数据类型和参数的最大长度。Add方法导致生成一个参数对象,其类型是Parameter,你可以将Add方法生成的参数对象存储到一个类型为Parameter的变量中,也可以像示例中的程序一样直接给Parameter对象的Value属性赋值。所赋的值是从客户编号文本框中取得的内容。
在程序中,调用命令对象的ExecuteNonQuery方法执行插入命令,在此以前通过执行数据连接对象oleDbConnection1的Open方法建立与数据库的连接,执行完命令后再调用数据连接对象的Close方法关闭与数据库的连接。
程序的最后是刷新客户信息。
运行程序,输入客户编号10999的相应信息,点击“插入”按钮,新记录显示在客户信息中。
方法二:使用数据集完成插入操作

数据表的NewRow()方法创建一个与数据结构相同的数据行,即创建的新数据行与数据的数据行有相同的列。无法使用new DataRow()构造一个数据行对象,因为DataRow的构造方法无法访问。
构造的新行可以通过调用数据表的Rows集合属性的Add()或InsertAt()方法添加到指定的数据表。虽然上面的代码构造数据行和添加数据行使用的都是Customer数据表,但这两个操作并没有这样的要求,但添加到数据表的数据行必须和数据表有相同的结构。
后续的代码调用数据适配器的Update()方法将数据集dataSet11的Customer数据表的更新写到数据库。Update()方法是通过在数据库服务器上执行其命令对象属性DeleteCommand、InsertCommand和UpdateCommand中的SQL命令完成相应的更新操作。在执行Update()方法时,数据适配器会依次检索相应数据表中的行,根据数据行的“插入”、“删除”和“更新”标记完成数据库的更新操作。如果没新插入的行,则适配器并不会将相应的Insert命令发送给数据库服务器。
数据适配器的Update()方法的执行流程如下:
(1) 数据适配器根据数据表中插入的新行填充相应INSERT命令对象属性InsertCommand的参数,如果命令参数与插入新行的列不匹配则抛出异常;如果没有新行则执行(6);
(2) 如果INSERT命令对象的连接还没有打开,则打开相应的连接;
(3) 将INSERT SQL命令发送给数据库服务器执行;
(4) 服务器执行完后回送给数据适配器一个执行结果的信息,如果命令无法执行则抛出异常;
(5) 如果INSERT命令对象的连接是在执行Update()方法时执行了打开操作,关闭相应的连接;
(6) 类似(1)-(5)完成删除记录的操作;
(7) 类似(1)-(5)完成修改记录的操作;(注:三种操作的顺序可能并不是这样)
(8) Update()方法执行完毕。

7.1.5. 删除功能的实现
(1) 双击“删除”按钮,Visual Studio自动添加该按钮的Click事件处理程序btnDelete_Click,其中,btnDelete是该按钮的控件名称。
(2) 添加事件处理程序btnDelete_Click相应的内容,完整的程序如图 7 10,
Click事件处理程序根据用户在客户信息列表中的选择删除所选择的客户记录。程序首先从数据网格dataGrid1的当前行获得客户编号,具体的方法是
this.dataGrid1[this.dataGrid1.CurrentRowIndex,0]
其中,CurrentRowIndex是数据网格的属性,表示当前行的序号(从0开始),因为第1列显示的是客户编号,所以以上代码从用户选择的行中取第1列的值,即客户编号。
与前面插入操作的事件处理程序不同,在构造DELETE删除命令时没有使用参数,而是直接把获取的客户编号加入到DELETE命令中。
其它的内容与前面插入操作的编程相似,这里不再作进一步的说明。如果有时间的话,也可以将打开与数据库的连接、执行命令和关闭数据库的连接编写成一个方法,在插入和删除操作的事件处理程序中调用该方法,这样可以提高程序的复用性。刷新客户列表信息的操作也可以编写一个方法。
方法一:使用命令对象
图 7 10 删除按钮的事件处理程序
方法二:使用数据适配器的命令对象

数据适配器对象oleDbDataAapter1有DeleteCommand、InsertCommand、UpdateCommand和SelectCommand四个命令对象属性,它们的类型为OleDbCommand。数据适配器的命令对象属性的类型与数据适配器的类型有关,如果适配器对象的类型为SqlDataAapter,则其命令对象属性的类型为SqlCommand。
使用数据适配器命令对象属性与创建单独的命令对象完成删除记录的操作没有本质上的区别。
方法三:使用数据集删除记录

除了使用命令对象完成删除记录的操作方法外,还可以通过修改数据集完成删除记录的操作。每个数据集有一个类型为DataTableCollection的数据表集合属性Tables,要访问某一个数据表可以通过索引如Tables[0]表示第1个表,或者数据表名如Tables[“Customer”]表示数据集中的Customer数据表。
每个数据表有一个类型为DataRowCollection的行集合属性Rows,其元素的类型为DataRow。可以使用列索引或数据表列名访问行集合中的元素,如Rows[0][0]和Rows[0][“CustomerID”]分别表示数据中的第1行的第1列和第1行的CustomerID列。
DataRow对象的Delete()从数据表中删除该数据行对象。但需要注意的是,Delete()方法仅是在数据行对象上打上“已删除”的标记,并不会真正从数据表中删除该行,因为,使用数据适配器将数据集中数据表的更新写到数据库时还需要该行的信息。当然,Delete()不会更新数据库。如果要从数据表中删除数据行,则调用数据的Rows集后属性的Remove()或RemoveAt()方法。
注释:实际上,数据集对象并不与数据库交互,它并不提供更新数据库的手段或其它任何操作数据库的手段,与数据库的交互是数据适配器对象的任务。
7.1.6. 更新功能的实现
由于dataGrid1对象绑定的数据为数据集dataSet11中的数据表Customer,因此,在dataGrid1中可直接修改相应的内容,然后调用数据适配器的Update()方法,更新就会保存到数据库。
需要注意的是,CustomerID的修改可能会导致违反引用性约束。
7.1.7. 如何运行该示例
本节给出的示例的完整文件可以到公共邮箱下载。示例是使用Visual Studio 2012和C#语言开发的,与连接的SQL Server数据库的版本没有联系,但要保证程序连接的数据库服务器中有的示例数据库Example和Customer和SalesOrderHeader表。
运行该示例需要做以下的工作:
(1) 创建Example数据库。可以选择下面的方法之一创建Example数据库:
 使用前面的命令创建表Customer和SalesOrderHeader。
 通过“附加”数据库添加Example。
(2) 修改连接信息。下载的示例中的连接信息可能与你的SQL Server环境并不相同,可以通过下面的方法之一修改连接对象的内容:
 方法一:直接修改数据连接对象的ConnectString属性,将其中的Data Source=GUO-PC\SQLEXPRESS的数据库服务器名修改为你自己的数据库服务器名。
 方法二:选择“视图/服务器资源管理器”菜单,打开“服务器资源管理器”,修改数据连接对象对应的数据连接或创建一个新的数据连接,然后再到数据连接对象oleDbConnection1的属性面板中修改其ConnectString属性,点击右边的下拉边框并从中选择相应的连接。
 方法三:重新运行数据适配器配置向导。选择oleDbAdapter1数据适配器对象,点击右键弹出菜单,选择“配置数据适配器”。
7.2. 订单查询
图 7 13显示了订单查询程序的用户界面。在用户界面上,可以在“客户姓”(表示LastName)文本框和“名”(表示FisrtName)文本框中输入客户的LastName和FirstName,在“发货日期”中选择或输入发货日期(表示ShipDate)。如果相应的条件为空,则表示没有该查询条件。图中显示的查询条件为:LastName的值为“Elson”,ShipDate的值为2005年7月8日。
窗体的下面是一个显示查询结果的DataGrid,第一次运行时,显示所有的订单。相应的查询语句为:

点击“查询”按钮在下面的DataGrid中显示如图 7 15所示的查询结果。

程序的创建流程如下:
(1) 创建Windows窗体应用程序项目

(2) 在窗体上添加相应的控件,如下表所示:
名称 类型 作用
tbxLastName TextBox 输入客户姓
tbxFirstName TextBox 输入客户名
tmpShipDate DateTimePicker 输入发货日期
btnSelect Button 查询按钮
dataGrid1 DataGrid 查询查询结果

(3) 将数据适配器组件从工具箱中拖到窗体Form1上,数据适配器配置向导启动,配置后的连接对象olDbConnection1和数据适配器对象olDbDatapAdapter1出现在组件窗口。
数据连接对象的连接字符串如下:

数据适配器的查询命令对象的查询命令如图 7 14所示。因为数据适配器的查询命令是两个表的连接查询,所以,数据适配器配置向导不会自动生成数据适配器的Delete、Insert和Update命令对象。如果需要,可以在设计器中手工修改或在程序中编码修改数据适配器的DeleteCommand、InsertCommand和UpdateCommand属性。
(4) 使用数据适配器oleDbDataAdapter1生成数据集,数据集的类型为DataSet1,数据集对象dataSet11被自动添加到程序中并出现在组件窗口;
(5) 设置数据控件dataGrid1的数据绑定。属性DataSource为dataSet11,DataMember为Customer。
(6) 设置窗体的加载事件,其代码如下:
(7) 设置查询按钮的Click事件处理程序,实现订单查询功能。具体的代码如下:
订单查询按钮的事件处理程序中,因为发货日期只是判断日期部分(年、月、日)的值是否相等,而没有对时间部分(小时、分、秒等)进行判断,因此,使用T-SQL的CAST()函数将DateTime类型的ShipDate转换为Date类型,将输入的发货日期和时间的字符串也转换为Date类型。
如果要判断日期早于或易于某一时间,可以直接使用小于或大于。
7.3. 实验内容与要求
使用ADO.NET并任选一种程序设计语言进行编程。
实验报告需要说明所采用的方法、结果和总结(结果分析)。
实验方法部分说明采用的开发环境,包括操作系统、数据库管理系统及其版本、编程工具及其版本、和编程语言。如果使用ADO.NET则在实验方法部分回答下面的问题:
(1) 使用哪种数据提供程序?
(2) 使用的数据连接对象是哪一个?连接对象是如何建立的?最后生成的连接对象中的连接字符串是什么?代表什么含义?
(3) 使用的数据适配器对象是什么?其中的查询或更新语句是什么?如果有参数则参数是如何处理的?
(4) 使用的数据集对象是什么?数据集中有哪些数据表?数据表是由哪些适配器对象生成的?(或采用其它方法)。
实验方法中还需要给出手工添加的代码及对代码的说明。
实验结果部分给出程序运行的界面和操作的简单说明。
总结部分对实验过程中出现的总是进行分析,同时提出所开发的程序还有哪些可以改进的地方。
7.3.1. 实验一:合同管理系统查询功能的程序实现
(1) 查询合同。首先列表所有的合同(包括合同编号、合同名称、签订日期、销售负责人),然后可以输入合同编号或合同名称查询某一特定合同的内容。
表 7 1 合同一览表
编号 合同名称 签订日期 销售 合同额
1 北京理工大学校园网一期 2006-1-1 张军 1000000.00
2 北京地理研究所存储系统 2006-2-10 赵蕊 500000.00
3 上海通用备份系统 2006-5-8 张军 7400000.00
4 北京理想公司存储系统 2006-5-30 李向阳 1500000.00
5 北京重工 2006-7-1 李向阳 3000000.00
6 北京大学备份系统 2006-8-8 王桐 3800000.00
7 北京理工大学备份系统 2006-8-9 王桐 4000000.00

(2) 查询应付款项。根据合同的内容查询目前已经付款总和小于合同总额的且已经超过合同所规定的付款日期的合同信息,包括应付款款项和应付款的日期,将相应的内容通知销售负责人以便进行应付款摧交。参考格式如下:
表 7 2 应付款款项
销售 合同编号 合同名称 应付款 应付日期
张军 1 北京理工大学校园网一期 1000000.00 2006-12-1
张军 3 上海通用备份系统 6500000.00 2006-12-4
李向阳 5 北京重工 230000.00 2006-11-1

(3) 员工基本信息维护,查询、添加、修改和删除员工的信息。

你可能感兴趣的:(SQL,Server)