在 Visual Studio .NET 中使用 SQL Server 2000 创建数据库应用程序(1)
Clarity Consulting Inc.
2002 年 3 月
适用于:
Microsoft? SQL Server? 2000
Microsoft Visual Studio? .NET
摘要:如何使用 Visual Studio .NET 工具创建数据库对象和 Transact-SQL 存储过程。
目录
简介
Microsoft? Visual Studio? .NET 包括一系列工具和数据访问类,使通过 Microsoft SQL Server? 2000 生成数据库应用程序比以前更加容易。现在,开发人员所需的所有工具都包含在 Visual Studio 集成开发环境 (IDE) 中。本白皮书将介绍新的工具和数据类,引导您完成生成数据库应用程序的整个过程,并重点介绍对 SQL Server 2000 新增功能(例如 XML 支持、索引视图和级联引用完整性)的支持。本文还包括一个简单的 Microsoft Visual Basic? 应用程序,用于阐明如何使用这些工具。
前提条件
要生成本文中的示例应用程序,您的计算机上必须安装以下软件:
- Microsoft Windows? 2000 Server
- Visual Studio .NET(有些示例程序注明需要使用 Visual Studio .NET Enterprise Edition)
- SQL Server 2000 Enterprise Edition
还需要使用数据库所有者 (dbo) 权限登录 SQL Server。
可视化数据库工具
Visual Studio .Net IDE 包含一套可视化数据库工具,旨在简化使用 SQL Server 2000 开发数据库应用程序。可视化数据库工具包含以下各项:
- 服务器资源管理器
- 数据库设计器
- 表设计器
- SQL 编辑器
- 查询和视图设计器
以下各节将详细介绍这些工具。
服务器资源管理器
服务器资源管理器是可视化数据库工具以及多数其他工具和设计器的门户。使用服务器资源管理器,您可以连接到 SQL Server 数据库并查看带有 SQL Server 计算机、数据库关系图、表、视图、存储过程和函数等节点的分层结构树状视图。许多开发人员以前需要使用 SQL Server 企业管理器才能完成的任务,现在可以使用服务器资源管理器来完成,而无需再使用企业管理器。
要打开服务器资源管理器,请启动 Visual Studio .NET,然后在 View(视图)菜单中单击 Server Explorer(服务器资源管理器)。
第一次打开服务器资源管理器时,会看到两个节点,如图 1 所示。第一个节点 Data Connections(数据连接)列出了计算机上以前创建的所有数据库连接。第二个节点 Servers(服务器)列出了当前网络上的所有服务器。Servers(服务器)节点下有一个名为 SQL Servers(SQL 服务器)的节点,使用该节点可以访问可视化数据库工具而无需创建数据连接。创建数据连接后,也可以通过 Data Connections(数据连接)节点访问可视化数据库工具。
图 1:服务器资源管理器(单击图片以查看大图像)
创建新的 SQL Server 数据库
使用 Visual Studio .NET Enterprise Edition,用户可以在 Visual Studio .NET IDE 中创建新的 SQL Server 数据库。在以下过程中,我们将创建一个名为 ServiceCall 的示例数据库。
创建新的数据库
- 打开服务器资源管理器:在 View(视图)菜单中,单击 Server Explorer(服务器资源管理器)。
- 右键单击 Data Connections(数据连接),然后单击 Create New SQL Server Database(创建新 SQL Server 数据库)。将打开 Create Database(创建数据库)对话框。
图 2:创建新 SQL Server 数据库
- 在 Create Database(创建数据库)对话框中,执行以下操作:
- 在 Server(服务器)中,键入服务器的名称。
- 在 Login Name(登录名)和 Password(密码)中,输入新数据库的身份验证信息。
- 在 New Database Name(新数据库名)中,键入 ServiceCall,然后单击 OK(确定)。
图 3:Create Database(创建数据库)对话框
新数据库在服务器上使用默认设置创建,并带有指向新数据库的数据连接。单击数据库旁边的加号 (+) 可以展开数据库关系图、表、视图、存储过程和函数等节点。
表设计器
可以使用表设计器创建和维护来自服务器资源管理器的数据库表。
要启动表设计器,请右键单击 Tables(表)节点(该节点位于创建 ServiceCall 数据库时所创建的数据库连接下),然后单击 New Table(新建表)。
表设计器包括两部分。顶部包含一个网格,从中可以定义表中的列。Data Type(数据类型)下拉列表包括所有有效的数据类型,其中一些类型专用于 SQL Server 2000(Bigint 和 Sql_variant)。底部包含一个选项卡,从中可以指定其他列特性,就像在企业管理器的表设计器中一样。
创建表
在以下过程中,我们将为 ServiceCall 数据库创建 Customers 表和 ServiceCall 表。
创建 Customers 表和 ServiceCall 表
- 如图 4 所示,定义 Customers 表的列。
图 4:Customers 表的表设计器属性表(单击图片以查看大图像)
- 右键单击 CustomerID 列,然后单击 Set Primary Key(设置主键);或者使用工具栏上的 Set Primary Key(设置主键)控件。
- 单击 Save(保存),然后在 Choose Name(选择名称)对话框中键入 Customers。
- 对 ServiceCall 表重复此过程,将 ServiceCallID 设置为主键,将 Identity 属性设置为 Yes,如图 5 所示。
图 5:ServiceCall 表的表设计器属性表(单击图片以查看大图像)
除了在表中定义列和键以外,用户还可以使用表设计器创建和修改表的关系、约束和索引等。
创建 ServiceCall 表和 Customers 表之间的关系
- 打开 ServiceCall 表的表设计器,右键单击列网格中的任意位置,然后选择 Relationships(关系);或者使用工具栏上的 Manage Indexes and Keys(管理索引和键)控件。屏幕将显示 Property Pages(属性页)对话框。
- 单击 Relationships(关系)选项卡,然后单击 New(新建)。关系名称默认为 FK_ServiceCall_Customers。
- 将主键表定义为 Customers,将主键列定义为 CustomerID。
- 将外键表定义为 ServiceCall,将外键列定义为 CustomerID。
图 6:Property Pages(属性页)对话框
- 单击 Close(关闭),然后单击 Save(保存)。
这样,SQL Server 将确保 ServiceCall 数据库不会在 ServiceCall 表中包含这样的行,即其 CustomerID 不会出现在 Customers 表中。
在表设计器中,一个专门用于 SQL Server 2000 的功能是定义级联引用完整性。
在表之间声明引用完整性
- 在服务器资源管理器中,右键单击 Customers 表,然后选择 Design Table(设计表)。将打开表设计器。
- 单击 Relationships(关系)。将显示 Property Pages(属性页)对话框,其中已选定 Relationships(关系)选项卡。在对话框底部,有以下两个选项:
- Cascade Update Related Fields(级联更新相关字段)- 在主键更新后,使数据库将新键值传播到相应的外键。
- Cascade Delete Related Records(级联删除相关的记录)- 删除主键表中的行时,使数据库从外键表中删除相应的行。
- 选择 Cascade Delete Related Records(级联删除相关的记录),单击 Close(关闭),然后单击 Save(保存)。设置此选项将使 SQL Server 从 ServiceCall 表中删除与从 Customers 表中删除的每行的 CustomerID 匹配的所有行。
注意:系统将显示一个 Save Warning(保存警告)对话框,其中显示消息“以下各表将保存到数据库中。是否继续?”。将列出 Customers 表和 ServiceCall 表。单击 Yes(是)。显示保存警告信息是因为打开了 Warn about Tables Affected(表受到影响时警告)选项;您可以在 Save Warning(保存警告)对话框中关闭此选项。
图 7:选中了 Cascade Delete Related Records(级联删除相关的记录)的 Relationships(关系)选项卡
重要信息:要使用示例数据填充表,请在 SQL 查询分析器中运行附录 1 中的数据库加载脚本。
数据库设计器
数据库设计器是一个图形界面,可用于添加或修改数据库表、关系、索引、键和约束等。
注意:数据库设计器要求使用 Visual Studio .NET Enterprise Edition。
您可以为给定的数据库创建任意数目的关系图,一个表可以出现在任意数目的关系图中。这些关系图还可以用来记录数据库的设计。
使用 SQL Server 数据库关系图时,需要注意一些事项。有关详细信息,请参阅 Visual Studio .NET 文档中的“SQL Server 数据库的数据库设计器注意事项”。该主题包含了更改数据类型、区分大小写以及其他信息。
创建数据库关系图
- 打开数据库设计器:在服务器资源管理器的数据库节点下,右键单击 Database Diagrams(数据库关系图),然后单击 New Diagram(新建图表)。将打开数据库设计器,并显示 Add Table(添加表)对话框,从中可以将现有表添加到关系图中。
- 将 Customers 表和 ServiceCalls 表添加到关系图中,然后单击 Close(关闭)。
- 关闭数据库设计器,然后保存该关系图(如果需要)。
创建关系图后,您可以右键单击关系图的背景将新表添加到关系图或数据库中。也可以右键单击一个表以维护列、键、索引、约束和关系等。数据库设计器与 SQL Server 企业管理器中的关系图工具非常类似(参阅图 8)。
图 8:数据库设计器关系图窗格
示例应用程序
为了演示其余的可视化数据库工具和数据访问类,我们将使用刚刚创建的 ServiceCall 数据库生成一个示例应用程序。
要开始示例应用程序,需要创建一个新的 Visual Studio .NET 项目。
创建新项目
- 在 File(文件)菜单中,选择 New(新建),然后单击 Project(项目)。
- 在 Project Types(项目类型)下,单击 Visual Basic Projects(Visual Basic 项目),然后在 Templates(模板)下,单击 Windows Application(Windows 应用程序)。
- 将项目命名为 ServiceCall,然后单击 OK(确定)。这样便创建了一个解决方案和一个项目,两者都名为“ServiceCall”。每个 Visual Studio .NET 解决方案都可以包含一个或多个项目。
- 打开服务器资源管理器窗口:在 View(视图)菜单中,单击 Server Explorer(服务器资源管理器)。如果展开 Data Connections(数据连接)节点,可以看到先前创建的指向 ServiceCall 数据库的连接。
生成此示例应用程序的第一步是创建一个用户定义的函数,以计算一个服务调用的总成本 ((LaborRate * Hours) + PartsCost)。用户定义的函数可以是标量值函数或表值函数(创建用户定义的函数要求使用 Visual Studio .NET Enterprise Edition)。标量值函数返回一个标量数据类型的单个值,并且可以显示在任何显示列名称的查询中。表值函数返回一个表,可用于 Transact-SQL 查询的 FROM 子句中。在 Visual Studio .NET 中,可以创建三种类型的用户定义函数:
- 标量值函数 - 返回单个标量值的函数。
- 内联函数 - 一种表值函数,返回通过单个 SELECT 语句定义的表值。
- 表值函数 - 一种表值函数,返回一个通过多个 Transact-SQL 语句定义的表。表值函数也称为多语句函数。
创建函数
- 在服务器资源管理器中刚刚创建的连接下,右键单击 Functions(函数)节点,然后选择 New Scalar-valued function(新建标量值函数)。将打开 SQL 编辑器,该编辑器用于创建和维护函数及存储过程。系统提供了一个模板帮助您创建函数。
- 复制以下代码并将其粘贴到 SQL 编辑器中以创建函数:
Create FUNCTION dbo.ComputeServiceCallTotal(@LaborRate money = 0, @Hours float = 0, @PartsCost money = 0)RETURNS moneyASBEGIN RETURN ((@LaborRate * @Hours) + @PartsCost)END
- 单击 Save(保存)保存函数,或者在 File(文件)菜单中,单击 Save <function name>(保存 <函数名称>)。函数将作为对象保存在数据库中。
SQL 编辑器
SQL 编辑器使用颜色代码区分 Transact-SQL 关键字,从而尽可能减少语法错误并使代码更易于阅读。它还提供了用来创建新函数和存储过程的模板。SQL 编辑器还在每个 Transact SQL 语句的周围放置了细线框,用于将 Transact-SQL 代码分隔成命令段,并标识可以使用查询和视图设计器生成和修改的 Transact-SQL 语句块。
查询和视图设计器
为了演示查询和视图设计器是如何工作的,我们将在服务器资源管理器中创建一个存储过程,该存储过程使用了我们刚刚创建的函数。
创建存储过程
- 在 ServiceCall 连接下,右键单击 Stored Procedures(存储过程)节点,然后单击 New Stored Procedure(新建存储过程)。这将打开 SQL 编辑器窗口,其中带有一个新的存储过程模板。
图 9:创建存储过程模板
- 在 SQL 编辑器窗口中,为 BrowseInvoiceTotals 存储过程键入以下代码:
Create PROCEDURE dbo.BrowseInvoiceTotals as Declare @TotalInvoice as money Set @TotalInvoice = dbo.ComputeServiceCallTotal(50, 5, 200) Select c.CustomerID, c.CustomerName, sc.ServiceDate, dbo.ComputeServiceCallTotal(sc.LaborRate, sc.Hours, sc.PartsCost) as TotalInvoice From Customers c Inner Join ServiceCall sc on c.CustomerID = sc.CustomerIDReturn
注意:用来声明和计算硬编码的 @TotalInvoice 值的代码仅用于演示目的。
- 完成存储过程后,单击 File(文件)菜单中的 Save(保存),将存储过程保存在数据库中。
请注意 SELECT 语句周围的细线框。在 Transact-SQL 查询框中单击右键,然后单击 Design SQL Block(设计 SQL 块)。这将启动查询和视图设计器,可用于以图形化的方式生成或修改查询(参阅图 10)。
图 10:查询和视图设计器表(单击图片以查看大图像)
查询和视图设计器包括四个部分。最上面的部分包含关系图窗格,其中显示正在查询的表。您可以添加或删除表、选择或取消选择列、添加或删除表联接以及在此部分中按列指定顺序。第二部分包含网格窗格,其中显示查询中的列,并允许您选择排序类型和排序顺序、过滤标准以及按列分组。第三部分包含 SQL 窗格,其中显示查询的 SQL 语法。如果在此窗格中修改查询,其他窗格将更新以反映这些更改。如果对查询所做的更改无法在其他窗格中表示出来,这些更改将不可用。第四部分包含结果窗格,其中显示执行查询后的查询结果。
查询和视图设计器对于视图和查询的工作原理相同,只是有些功能是专用于视图的。其中一个专用于 SQL Server 2000 的功能就是创建索引视图。
创建索引视图
- 打开服务器资源管理器,右键单击 Views(视图),然后单击 New View(新建视图)。将显示 Add Table(添加表)对话框。
- 将 Customers 表添加到视图中,然后关闭 Add Table(添加表)对话框。
- 在关系图窗格中,选中 CustomerID 复选框和 CustomerName 复选框。
- 要使用索引,请右键单击关系图窗格的背景,然后单击 Manage Indexes(管理索引)。这将打开 Indexes(索引)对话框,从中可以指定关联的索引。您必须对视图中的表具有适当权限才能创建索引视图。
- 关闭 Indexes(索引)对话框,然后关闭查询和视图设计器。
您也可以使用查询设计器浏览表和更新表的内容。
- 在服务器资源管理器中,依次展开 ServiceCall Data Connection(ServiceCall 数据连接)节点和 Tables(表)节点并右键单击一个表,然后单击 Retrieve Data from Table(从表中检索数据)。
与表内容一同出现的数据网格就是查询设计器数据网格。请注意,一个工具栏将与数据网格一同打开,该工具栏可用于访问关系图窗格、SQL 窗格、网格窗格以及查询设计器的结果窗格。同样,这些功能也非常类似于企业管理器中的功能。
调试存储过程
服务器资源管理器中另外一个强大的功能是存储过程调试。要调试 BrowseInvoiceTotals 存储过程,请打开服务器资源管理器,然后定位到 ServiceCall 连接中的 Stored Procedure(存储过程)节点。右键单击 BrowseInvoiceTotals,然后单击 Step Into Stored Procedure(单步执行存储过程)。也可以双击存储过程打开编辑器,然后单击 Database(数据库)菜单中的 Step Into Stored Procedure(单步执行存储过程)。
按 F11 键单步执行存储过程,并注意当执行到语句 Set @TotalInvoice = dbo.ComputeServiceCallTotal(50, 5, 200) 时,调试器将离开存储过程并进入该函数。完成函数的调试后,调试器将返回存储过程。可以将鼠标指针移到 @TotalInvoice 变量之上,或者右键单击该变量并设置一个观察变量,以查看该变量的内容。也可以在 Locals(本地变量)窗口中查看变量的内容:在 Debug(调试)菜单中,突出显示 Windows(窗口),然后单击 Locals(本地变量)。在图 11 中,执行 Set 语句后,Locals(本地变量)窗口中显示 @TotalInvoice 的值为 450.0000。同样,从 Visual Studio .NET IDE 中也可以访问 Transact-SQL 语句调试工具。
图 11:SQL 调试器窗口表(单击图片以查看大图像)
SQL 调试器具有某些局限性,其中包括:
- 表变量不能在 Locals(本地变量)窗口中显示。
- Sql_variant、text、ntext、image 和 cursor 变量可以在 Locals(本地变量)窗口中显示,但只能用于显示。
- 不支持大于 64 KB 的存储过程。
- 不支持超过 32 层嵌套存储过程调用。
- 不支持向一个存储过程传递的参数超过 1023 个。
有关其他局限性,请参阅 SQL Debugging Limitations(英文)。
注意:SQL 调试器使用分布式组件对象模型 (DCOM) 进行客户端计算机和 SQL Server 之间的通信。为了使调试器能够正常工作,必须使用 Dcomcnfg.exe 设置正确的 DCOM 权限。有关详细信息,请参阅 Troubleshooting the Transact-SQL Debugger(英文)。此外,要进行调试,SQL Server 不能作为系统帐户运行。与 MSSQLSERVER 服务相关联的登录必须是一个有效的用户帐户。
数据集
现在,我们已具备 ServiceCall 数据库和连接、一个用户定义的函数以及一个存储过程。下一步,我们将使用该存储过程来创建一个用于填充数据网格的数据集。
创建数据集
- 打开工具箱:在 View(视图)菜单中,单击 Toolbox(工具箱)。
- 在工具箱中,单击 Data(数据)选项卡,然后将一个 SqlDataAdapter 控件拖到 Form1 上。这将在 Form1 的设计窗口底部放置一个 SqlDataAdapter1 图标,并启动数据适配器配置向导。数据适配器配置向导收集与适配器将要管理的数据有关的信息。
- 当向导提示您提供要使用的数据连接时,请指定 ServiceCall 连接。
图 12:选择数据连接属性表
- 下一步,从以下选项中选择一种查询类型:
- Use SQL statements(使用 SQL 语句)- 提供 Transact-SQL 语句或使用查询生成器以图形方式设计查询。
- Create new stored procedures(创建新存储过程)- 向导自动基于自身提供的 Transact-SQL 语句创建选择、插入、更新和删除等存储过程。
- Use existing stored procedures(使用现有存储过程)- 最多可以指定四个现有的存储过程,分别对应以下四种操作。您不必指定全部四个存储过程。对于指定的每个存储过程,SqlDataAdapter 被配置为将存储过程与相应的数据库操作相关联:
选择 - 从数据库中读取现有数据
插入 - 向数据库的一个或多个表中插入新行
更新 - 更新现有的行
删除 - 删除现有的行
无论选择何种查询类型,都可以选择使用图形化的查询工具来生成查询,并从以下高级 Transact-SQL 生成选项中进行选择:
- Use the Select statement(使用 Select 语句)- 基于 Select 语句生成 Insert、Update 和 Delete 语句。
- Use optimistic concurrency(使用开放式并发)- 修改 Update 和 Delete 语句以确定在记录被加载到数据集后数据库是否发生了改变。
- Refresh the dataset(刷新数据集)- 添加一个 Select 语句以检索标识列值并刷新由数据库计算的值。
选择 Use existing stored procedures(使用现有存储过程)作为查询类型。
图 13:选择查询类型属性表
- 在 Bind Commands to Existing Stored Procedures(将命令绑定到现有存储过程)页面的 Select(选择)下拉列表框中,选择 BrowseInvoiceTotals。
图 14:将命令绑定到现有存储过程属性表
- 忽略 Insert(插入)、Update(更新)和 Delete(删除)下拉列表。单击 Next(下一步),然后单击 Finish(完成)。
图 15:查看向导结果
下一步,我们将配置 SqlDataAdapter 生成的数据集。
配置数据集
- 在 Form1 上右键单击 SqlDataAdapter1 图标,然后单击 Generate Dataset(生成数据集)。
图 16:为 SqlDataAdapter 生成数据集
- 在 Generate Dataset(生成数据集)对话框中,选择 New dataset(新建数据集),然后键入名称 BrowseInvoiceTotalsDS。
- 位于页面底部的窗口中的 BrowseInvoiceTotals(SqlDataAdapter1) 应已被选中。单击 OK(确定)。
图 17:生成数据集属性表
下一步,我们将为 Form1 创建窗体元素。
创建窗体元素
- 向 Form1 添加一个 DataGrid 控件。
- 打开工具箱,然后单击 Windows Forms(Windows 窗体)。
- 将一个 DataGrid 控件拖放到 Form1 上,右键单击 DataGrid 控件,然后单击 Properties(属性)。将 DataGrid 控件的 CaptionText 属性更改为 Invoice Report。
- 配置 DataGrid 控件的属性,以将其绑定到数据:在 Properties(属性)下的 Data(数据)部分中,将 DataSource 属性设置为 BrowseInvoiceTotalsDS1.BrowseInvoiceTotals。
图 18:DataGrid 属性页(单击图片以查看大图像)
- 调整 DataGrid 控件的大小,使所有的列都可见。
- 要填充数据集,请向 Form1 中添加一个按钮,然后将其 Text 属性和 Name 属性更改为 RunReport。
- 双击按钮打开代码窗口。将以下代码行添加到 RunReport_Click 子例程中并保存该应用程序:
BrowseInvoiceTotalsDS1.Clear' 使用 SqlDataAdapter 填充 DSSqlDataAdapter1.Fill(BrowseInvoiceTotalsDS1)
现在,可以测试我们的应用程序了。运行该应用程序,然后单击 RunReport 按钮。SqlDataAdapter 将连接到数据库,运行我们的存储过程和函数,加载数据集并将数据传递到数据网格中。输出结果应类似于图 19 所示的结果。
图 19:示例应用程序的输出
下一步,我们将创建一个数据维护窗体。
创建数据维护窗体
- 向 ServiceCall 项目添加一个新窗体 (Form2):在解决方案资源管理器中,单击右键项目名称,然后依次单击 Add(添加)和 Add Windows Form(添加 Windows 窗体)。
- 在 Templates(模板)下,单击 Windows Form(Windows 窗体)模板,然后单击 Open(打开)。
- 向窗体中添加一个 SqlDataAdapter 控件。将启动数据适配器配置向导。
- 为 SqlDataAdapter 选择现有的 ServiceCall 连接。对于此 SqlDataAdapter 控件,我们将让 Visual Studio .NET 为我们创建所需的存储过程。
- 单击 Create new stored procedures(创建新存储过程),然后单击 Next(下一步)。将打开 Generate the stored procedures(生成存储过程)页面。
- 单击查询生成器,将 Customers 表添加到查询,然后关闭 Add Table(添加表)对话框。
- 在关系图窗格中,选择所有的列,然后依次单击 OK(确定)和 Next(下一步)。
- 在 Create the Stored Procedures(创建存储过程)属性页中,分别为四个新存储过程提供一个名称(此示例中使用 CustomersSelect、CustomersDelete、CustomersInsert 和 CustomersUpdate),然后单击 Next(下一步)。
- 当向导的最后一页显示成功生成所有存储过程的消息时,单击 Finish(完成)。
- 打开 SqlDataAdapter 控件的属性页,查看以下属性;这些属性的值被设置为我们所提供的存储过程名称:
- SelectCommand.CommandText 的值为 CustomersSelect。
- DeleteCommand.CommandText 的值为 CustomersDelete。
- InsertCommand.CommandText 的值为 CustomersInsert。
- UpdateCommand.CommandText 的值为 CustomersUpdate。
Visual Studio .NET 创建了四个存储过程(基于我们提供的 Select 语句)、将其编译到数据库并配置了 SqlDataAdapter 控件以使用这些存储过程。
下一步要生成我们为 Form2 创建的 SqlDataAdapter 的数据集。
生成数据集
- 右键单击 SqlDataAdapter,然后单击 Generate DataSet(生成数据集)。
- 将数据集命名为 CustomersDS。
- 向窗体添加 DataGrid 控件,然后将该控件的 DataSource 属性设置为 CustomersDS1.Customers、CaptionText 属性设置为 Maintain Customers。
- 调整 DataGrid 控件的大小,使所有的列都可见。
- 在数据网格下添加一个按钮,将其 Text 属性和 Name 属性更改为 Load。
- 在第一个按钮旁添加另一个按钮,将其 Text 属性和 Name 属性更改为 Update。
- 双击 Load 按钮打开代码窗口,然后向 Load 按钮的单击事件中添加以下代码:
CustomersDS1.Clear()SqlDataAdapter1.Fill(CustomersDS1)
- 在 Update 按钮的单击事件中,添加以下代码:
SqlDataAdapter1.Update(CustomersDS1)
运行应用程序之前,必须将项目的 Startup 对象更改为 Form2。
更改 Startup 对象
- 在解决方案资源管理器中,右键单击 ServiceCall 项目,然后单击 Properties(属性)。
- 在 Startup object(启动对象)下,将 Startup 对象更改为 Form2,然后单击 OK(确定)。
运行应用程序以打开维护窗体 (Form2)。单击 Load 按钮加载带有表中现有数据的数据网格。屏幕应类似于图 20 所示。
图 20:示例应用程序输出结果(单击图片以查看大图像)
更新 ServiceCall 数据库
- 要删除行,请单击该行,然后按 Delete(删除)键。
- 要添加新行,请单击网格末尾空行中的任意单元格,然后提供相应的值。
- 完成更改后,单击 Update(更新)。
系统将检查网格中每一行的 RowStatus、调用相应的存储过程并传入正确的参数以处理请求的操作。
此示例展示了 Visual Studio .NET IDE 和框架的强大功能。我们仅使用了几行代码,就创建了功能完备的表维护应用程序。
使用 ADO.NET 访问 SQL Server
Microsoft .NET Framework 提供了名为 ADO.NET 的 ADO 的新版本。ADO.NET 功能得到了增强,能够更好地支持分布式应用程序的开发,并主要依赖 XML 作为其内部数据结构。
在以前版本的 ADO 中,Recordset 对象是开发人员用于处理来自数据存储的数据的主要对象。在 ADO.NET 中,DataSet 对象取代了 Recordset 对象。DataSet 是用户使用的数据在内存中的副本。DataSet 可以包含一个或多个 DataTables。您可以将 DataSet 视为一个虚拟关系数据库。DataSet 完全独立于原始数据源,而且不是用来与数据源进行直接通信。ADO.NET 是使用托管提供程序与数据源进行通信的。
ADO.NET 提供两种托管提供程序:一种用于 SQL Server 数据库,另一种用于任何 OLE DB 兼容数据库。到目前为止,我们创建的所有示例都使用了 SQL Server 托管提供程序。如果查看工具箱中 Data(数据)下的选项,您会注意到三对名称相同但前缀不同的控件。下表列出了这三对控件。
SQL Server | OLE DB |
---|---|
SqlDataAdapter | OLEDBDataAdapter |
SqlDataConnection | OLEDBDataConnection |
SqlCommand | OLEDBCommand |
前缀为 OLEDB 的控件表示 OLE DB 托管提供程序,可用于访问所有与 OLE DB 兼容的数据库。这些控件与当前的 ADO 对象类似,但已被改写为托管代码,因而可以在 .NET Framework 中使用。
前缀为 SQL 的控件表示 SQL Server 托管提供程序,只能用于 SQL Server。与其 OLE DB 的对应控件相比,这些控件具有一些优点。首先,这些对象使用本地表格数据流 (TDS) 接口以获得最佳性能。OLE DB 对象所需的其他接口层已被删除,这使数据库的访问速度更快。其次,从这些控件中创建的 SQL 对象具有其他一些方法,这些方法利用了专用于 SQL Server 的功能。这为使用 SQL Server 进行设计和编程提供了更大的灵活性。
我们在前面创建的示例应用程序中使用了 ADO.NET,而 Visual Studio .NET 为我们处理了大多数编码工作,我们所要做的就是通过 IDE 的用户界面配置数据集和数据适配器。现在,让我们看看使用 ADO.NET 从表中选择、插入、更新和删除数据时所需的 Microsoft Visual Basic? .NET 编码。首先看一下 Select 语句的代码:
Dim strCmdText As StringDim rowsProcessed As IntegerDim CustomerDS As New DataSet()strCmdText = "Select * from Customers"Dim SqlDataAdapter2 As New SqlDataAdapter(strCmdText, _ "Data Source=localhost;Initial Catalog=ServiceCall;User ID=sa;passsword=yourpassword")SqlDataAdapter2.Fill(CustomerDS, "Customers")
在此代码示例中,我们首先定义了要使用的变量和对象,其中包括 CustomersDS,它是一个 ADO.NET DataSet 对象。然后我们定义了查询,该查询将填充变量 strCmdText 中的数据集。下一步,我们定义一个 ADO.NET SqlDataAdapter 对象 (SqlDataAdapter2),将查询和数据库连接字符串作为参数提供。请注意,我们使用的是 SQL Server ADO.NET 托管提供程序。最后,通过调用 SqlDataAdapter 对象的 Fill 方法,填充 CustomerDS 并在名为 Customers 的 DataSet 中创建一个表。
因为 SqlDataAdapter2 是使用查询和连接串字符串定义的,所以 Fill 方法将建立到 SQL Server 数据库的连接、执行查询并将结果返回到 DataSet。
下一步,我们将看一看在表中插入行的代码:
Dim strCmdText As String Dim rowsProcessed As Integer Dim sqlConn As New SqlConnection _ ("Data Source=localhost;Initial Catalog=ServiceCall;User ID=sa;password=yourpassword") strCmdText = "INSERT INTO Customers VALUES ('Cust4', 'Customer Four', " _ & "'Cust4 Address', 'City', 'ST', '11111','(888)-123-4567')" Dim sqlCmd As New SqlCommand(strCmdText, sqlConn) sqlCmd.Connection.Open() rowsProcessed = sqlCmd.ExecuteNonQuery()
我们首先定义将要使用的对象和变量。然后创建一个 ADO.NET SqlConnection 对象 (sqlConn),并将连接字符串作为参数传递给该对象。然后定义查询,该查询将行插入到变量 strCmdText 中的 Customers 表中。
下一步,我们定义一个 ADO.NET SqlCommand 对象,并将查询和 SqlConnection 对象作为参数传递给该对象。然后,我们打开 SqlCommand 对象上的连接,并调用 ExecuteNonQuery 方法。ExecuteNonQuery 方法返回数据库操作所影响的行的数目。
除了传递给 SqlCommand 对象的查询以外,更新和删除表的代码与插入操作的代码基本相同。本文列出了这些代码,但因为它与插入操作的代码相同,所以没有对该代码进行赘述。
以下代码将更新表中的一行:
Dim strCmdText As String Dim rowsProcessed As Integer Dim sqlConn As New SqlConnection _ ("Data Source=localhost;Initial Catalog=ServiceCall;User ID=sa;password=yourpassword") strCmdText = "Update Customers Set CustomerName = 'Updated Customer' " _ & "Where CustomerID = 'Cust4'" Dim sqlCmd As New SqlCommand(strCmdText, sqlConn) sqlCmd.Connection.Open() rowsProcessed = sqlCmd.ExecuteNonQuery()
以下代码将删除表中的一行。
Dim strCmdText As String Dim rowsProcessed As Integer Dim sqlConn As New SqlConnection _ ("Data Source=localhost;Initial Catalog=ServiceCall;User ID=sa") strCmdText = "Delete Customers Where CustomerID = 'Cust4'" Dim sqlCmd As New SqlCommand(strCmdText, sqlConn) sqlCmd.Connection.Open() rowsProcessed = sqlCmd.ExecuteNonQuery()
这些示例展示了如何使用 SqlCommand 对象的 ExecuteNonQuery 方法。SqlCommand 对象还具有其他几个方法,包括专用于 SQL Server 处理 XML 数据的方法。在下一个示例中,我们将介绍它的工作原理。
XML 和 Visual Studio .NET
SQL Server 2000 具有对 XML 的内置支持。其中一个功能是 Select 语句中的 For XML 子句,它返回一个作为 XML 的结果集。SqlCommand 对象具有 ExecuteXMLReader 方法,此方法利用 SQL Server 中的这一功能。
下一个示例将展示 SqlCommand 对象的另一个应用。我们将查询 Customers 表,将结果作为 XML 返回,然后在窗体的文本框中显示该 XML。
查询 Customers 表并将结果作为 XML 返回
- 向项目添加一个新窗体 (Form3) 并向该窗体添加一个文本框。将文本框的 MultiLine 属性更改为 True、Width 属性更改为 504、Height 属性更改为 152(如图 21 所示)。
图 21:TextBox 属性页(单击图片以查看大图像)
- 向窗体添加一个按钮,将此按钮的 Name 属性和 Text 属性更改为 GetXML。
- 双击该按钮打开单击事件的代码窗口,然后添加以下代码。请记住更改数据源、用户 ID 和密码,使其与您的服务器匹配。
Dim XMLTxtReader As Xml.XmlTextReader Dim StringBuilder As New System.Text.StringBuilder() Dim XMLOutput As String Dim SQLCommand As New System.Data.SqlClient.SqlCommand() Dim SQLServiceCallConn As New _ System.Data.SqlClient.SqlConnection _ ("Data Source=YourServer;Initial Catalog=ServiceCall;User ID=xx;password=yourpassword") SQLServiceCallConn.Open() SQLCommand.Connection = SQLServiceCallConn SQLCommand.CommandType = CommandType.Text SQLCommand.CommandText = "Select CustomerID, CustomerName," _ & "Phone from Customers for XML auto" ' 执行 SQL 并返回 XML XMLTxtReader = SQLCommand.ExecuteXmlReader() StringBuilder.Append(XMLTxtReader.GetRemainder.ReadToEnd) XMLOutput = StringBuilder.ToString() Me.TextBox1.Text = XMLOutput
您的代码窗口应类似与图 22 所示(数据源、用户 ID 和密码可能会有所不同)。
图 22:带有 GetXML_Click 子例程代码的 Form3 的窗体类(单击图片以查看大图像)
在此代码示例中,我们首先定义要使用的对象和变量。XMLTextReader 对象用于保存从数据库返回的数据。StringBuilder 对象用于根据 XMLTextReader 对象中的数据创建 XML 字符串。
首先,我们创建一个 SqlConnection 对象 (SQLServiceCallConn) 并传入数据库的连接参数。然后,设置 SqlCommand 对象 (SqlCommand) 的 CommandType 属性和 CommandText 属性。请注意,我们在查询中使用了 For XML Auto 语句。它指示 SQL Server 将查询结果作为 XML 字符串返回。
然后,使用 SqlCommand 对象的 ExecuteXmlReader 方法来执行我们的 Transact-SQL 语句。此方法旨在利用 SQL Server 2000 的本地 XML 支持并返回一个 XMLTextReader 对象。最后一步是使用 StringBuilder 对象从 XMLTextReader 对象中提取一个包含从 SQL Server 返回的 XML 的字符串。
可以通过导入 System.Text 和 System.Data.SqlClient 命名空间来缩短 StringBuilder、SqlCommand 和 SqlConnection 对象的完全限定名称(如图 23 所示)。为此,请在窗体类定义上方插入以下代码:
Imports System.TextImports System.Data.SqlClient
图 23:使用简写表示法定义 StringBuilder 和 SqlConnection 对象的源代码(单击图片以查看大图像)
要测试该应用程序,请将 Startup 对象更改为 Form3 并运行应用程序(按 F5 键)。单击 GetXML。Customers 表的内容将作为 XML 返回并显示在文本框中(如图 24 所示)。
图 24:示例应用程序输出结果(单击图片以查看大图像)
SQLXML 3.0
在前面的示例中,我们讨论了 SQL Server 对 XML 的内置支持,有时也称其为 SQLXML。SQLXML 3.0 包含以下托管类,可以简化 SQLXML 在 Visual Studio .NET 中的使用。
类 | 说明 |
---|---|
SqlXmlCommand 对象 | 将 XML 数据从 SQL Server 返回到一个新的或现有的 Stream 对象,或将数据返回到一个 XMLReader 对象。此对象还包含一个用于创建参数的方法。 |
SqlXmlParameter 对象 | 用于填充使用 SqlXMLCommand 对象创建的参数。 |
SqlXmlAdapter 对象 | 用 SQL Server 中的 XML 数据填充数据集。此对象还将更新应用于数据集中的 SQL Server 数据。 |
这些托管类允许您通过多种方法处理 SQL Server 中的 XML 数据,包括:
- 执行 SQL 查询以返回 XML 数据
- 对 XML 数据应用 XSL 转换
- 对 XML 数据执行 XPath 查询
对于最后一个示例应用程序,我们将扩展以前的示例,使用 SQLXML 托管类返回 SQL 查询中的 XML 数据。
重要信息:必须安装 SQLXML 3.0 才能运行此示例应用程序。SQL Server 2000 Web Services 工具包附带了 SQLXML 3.0,也可以从 SQLXML and XML Mapping Technologies(英文)下载 SQLXML 3.0。
必须将 SQLXML 组件引用添加到项目中后才能使用 SQLXML 托管类。
添加 SQLXML 组件引用
- 打开解决方案资源管理器:在 View(视图)菜单中,单击 Solution Explorer(解决方案资源管理器)。
- 在 ServiceCall 项目下,右键单击 References(引用),然后单击 Add Reference(添加引用)。
- 在 Add Reference(添加引用)对话框中,单击 .NET 选项卡。
- 找到名为 Microsoft.Data.SqlXml 的组件,并突出显示该组件。
- 单击 Select(选择),然后单击 OK(确定)。
- 保存 ServiceCall 项目。
- 打开 Form3.vb,在该窗体中 GetXML 按钮旁边添加一个新按钮,然后将新按钮的 Name 属性和 Text 属性更改为 SQLXML。
- 双击 SQLXML 按钮打开单击事件的代码窗口并添加以下代码。请记住更改数据源、用户 ID 和密码,使其与您的服务器匹配。
Dim strm As System.IO.Stream Dim sqlXmlCmd As New Microsoft.Data.SqlXml.SqlXmlCommand _ ("Provider=SQLOLEDB;Data Source=localhost;" _ & "Initial Catalog=ServiceCall;User ID=sa;password=yourpassword") sqlXmlCmd.CommandType = Microsoft.Data.SqlXml.SqlXmlCommandType.Sql sqlXmlCmd.CommandText = ("Select CustomerID, CustomerName," _ & "Phone from Customers for XML auto") strm = sqlXmlCmd.ExecuteStream() Dim streamRdr As New System.IO.StreamReader(strm) Me.TextBox1.Text = streamRdr.ReadToEnd().ToString
在此代码示例中,我们首先定义要使用的对象和变量。Stream 对象 (strm) 将保存从查询返回的 XML 数据。然后,定义 SqlXmlCommand 对象 (sqlXmlCmd),并将连接字符串作为参数传递给该对象。
下一步,设置 SqlXmlCommand 对象上的参数。CommandType 被设置为 Sql,它是一个默认值,在此列出以帮助您理解。CommandText 被设置为查询的值,该查询就是我们在此示例的第一部分使用的同一个查询。然后,我们将调用 SqlXmlCommand 对象的 ExecuteStream 方法,该方法将执行 SQL 语句,并将 XML 数据放入 Stream 对象中。
下一步,我们定义 StreamReader 对象 (streamRdr),并将 Stream 对象 (strm) 作为参数传递给该对象。这样将使用 XML 数据填充 StreamReader 对象。在最后一步中,我们将加载带有来自 StreamReader 对象的 XML 数据的文本框。
应仍将 Startup 对象设置为 Form3,然后保存项目、运行应用程序(按 F5 键)并单击 SQLXML 按钮。输出结果应该与单击 GetXML 按钮时的输出完全一样,如图 24 所示。
数据库项目
通过 Visual Studio .NET,您可以创建为脚本、查询、数据备份文件和命令文件提供储备库的数据库项目。创建和维护数据库项目的方法与其他 Visual Studio .NET 项目相同。通过解决方案资源管理器可以访问数据库项目,其中提供了解决方案内所有项目的分层视图。
创建数据库项目
- 打开解决方案资源管理器:在 View(视图)菜单中,单击 Solution Explorer(解决方案资源管理器)。
- 右键单击 Solution 'ServiceCall',突出显示 Add(添加),然后单击 New Project(新建项目)。
- 在 Project Types:(项目类型:)下,展开 Other Projects(其他项目)文件夹,然后单击 Database Projects(数据库项目)。
- 在 Templates(模板)下,单击 Database Project(数据库项目)模板。
- 将项目命名为 ServiceCallDB,然后单击 OK(确定)。
图 25:Add New Project(添加新项目)对话框(单击图片以查看大图像)
- 在 Add Database Reference(添加数据库引用)对话框中,选择 ServiceCall 数据库的连接,然后单击 OK(确定)创建项目。
图 26:Add Database Reference(添加数据库引用)对话框
生成创建脚本和导出数据
注意:生成创建脚本需要使用 Visual Studio .NET Enterprise Edition。
生成创建脚本工具是服务器资源管理器中另一个专用于 SQL Server 的功能,此工具有助于使开发人员的工作更加轻松。使用生成创建脚本工具,您可以编写整个数据库或者数据库中的选定对象的脚本文件。然后可以使用该脚本文件来恢复数据库或对象,或在其他服务器上部署数据库。
除了创建脚本外,您还可以从单个表中导出数据。这在测试过程中这是一个很有用的工具。如果需要进行多次重复测试,而在这期间表将被更新或删除,则可以将表中的数据导出到一个文件中,然后在每个测试开始时恢复,以提供一个一致的起点。
为了演示这些功能,我们将编写 Customers 表的脚本,并将数据导出到一个备份文件,以便能够将数据恢复到其初始状态。
生成脚本
- 在服务器资源管理器中的 Data Connections(数据连接)下,展开 Tables(表)节点,右键单击 Customers 表,然后单击 Generate Create Scripts(生成创建脚本)。如果使用的不是 Windows 2000 或者 Windows NT 的集成安全性,系统可能会提示您为运行 SQL Server 的计算机提供用户 ID 和密码。将打开 Generate Create Scripts(生成创建脚本)对话框(使用过 SQL Server 企业管理器的用户应该对此对话框非常熟悉)。
- 该对话框包含三个选项卡:General(常规)、Formatting(设置格式)和 Options(选项)。接受这三个选项卡的默认设置,然后单击 OK(确定)。将打开 Browse for Folder(浏览文件夹)对话框。请注意,Visual Studio .NET 已经选择了前面创建的数据库项目中的 Create Scripts 文件夹。
- 单击 OK(确定)。将创建 Customers 表的脚本,此脚本将置于 Database Project 文件夹中。
将创建以下四个文件。
文件 | 说明 |
---|---|
Dbo.Customers.tab | 包含一个用来创建表的 SQL 脚本 |
Dbo.Customers.kci | 包含一个用来创建主键和索引的 SQL 脚本 |
Dbo.Customers.fky | 包含一个用来创建外键的 SQL 脚本 |
Dbo.Customers.ext | 包含一个用来创建扩展属性的 SQL 脚本 |
将数据表导出到文件
- 在服务器资源管理器中,右键单击 Customers 表,然后单击 Export Data(导出数据)。将再次打开 Browse for Folder(浏览文件夹)对话框,并定位到数据库项目中的 Create Scripts(创建脚本)文件夹。
- 单击 OK(确定)。Customers 表中的数据将被放置在名为 Dbo.Customers.dat 的文件中。
数据库项目命令文件
重要信息:命令文件要求使用 Visual Studio .NET Enterprise Edition。
使用命令文件可以将数据库项目中的多个脚本打包到一个命令中,从而将多个脚本的处理简化为一个步骤。
创建命令文件
- 在解决方案资源管理器中,右键单击包含要打包的脚本的数据库项目文件夹(本示例中为 Create Scripts [创建脚本] 文件夹)。
- 单击 Create Command File(创建命令文件)。将显示 Create Command File(创建命令文件)对话框。
- 将文件命名为 RestoreCustomers.cmd。
- 选择要包含到文件中的验证类型和脚本。在本示例中,请单击 Add All >>(全部添加 >>),然后单击 Add Data(添加数据)。将显示 Add Data(添加数据)对话框。
- Add Data(添加数据)对话框显示该命令文件可以使用的所有数据文件。选择 Dbo.Customers.dat,然后单击 OK(确定)。
- 在 Create Command File(创建命令文件)对话框中,单击 OK(确定)。RestoreCustomers.cmd 文件将被置于 Create Scripts(创建脚本)文件夹中。
运行命令文件
- 在数据库项目中,右键单击命令文件,然后单击 Run(运行)。
注意:命令文件只有在 Windows 2000 Server 或更高版本中才能正常运行。
小结
本文中的示例演示了 Visual Studio .NET IDE 中内置的数据库工具的强大功能。无需退出 Visual Studio .NET IDE 即可生成完整的应用程序,其中包括数据库、用户定义函数、存储过程和应用程序代码。此外,我们还能使用 Visual Studio .NET IDE 中包含的同样丰富的调试工具,在存储过程上执行源代码级别的调试。Visual Studio .NET 为您提供了更快、更好地创建应用程序所需的工具。
附录 1: 数据库装载脚本
要使用示例数据填充 ServiceCall 数据库中的表,请在 SQL 查询分析器中运行以下数据库加载脚本。
Use ServiceCallInsert into Customers values('cust1','Customer One','123 Main St.','Chicago','IL','60601','(312) 555-1212')Insert into Customers values('cust2','Customer Two','248 Elm St.','Serverville','IL','60679','(872) 555-4519')Insert into Customers values('cust3','Customer Three','831 First St.','Netville','IL','60831','(763) 555-6728')Insert into ServiceCall (CustomerID, ServiceDate, LaborRate, Hours, PartsCost)values('cust1','Sep 14 2001 12:00AM', 55.00, 3, 200.00)Insert into ServiceCall (CustomerID, ServiceDate, LaborRate, Hours, PartsCost)values('cust1','Sep 17 2001 12:00AM', 55.00, 1.5, 70.00)Insert into ServiceCall (CustomerID, ServiceDate, LaborRate, Hours, PartsCost)values('cust1','Sep 19 2001 12:00AM', 55.00, 2, 0.00)Insert into ServiceCall (CustomerID, ServiceDate, LaborRate, Hours, PartsCost)values('cust2','Sep 25 2001 12:00AM', 60.00, 3.5, 180.00)Insert into ServiceCall (CustomerID, ServiceDate, LaborRate, Hours, PartsCost)values('cust3','Sep 27 2001 12:00AM', 65.00, 4.5, 275.00)
附录 2: 详细信息
有关 Microsoft .NET 技术的详细信息,请参阅以下 Web 站点。
附录 3: 关于作者
Matt Mannion 是 Clarity Consulting Inc. 的业务经理,Clarity Consulting Inc. 是位于芝加哥的一家技术咨询公司,也是 Microsoft 的金牌认证伙伴。Matt 为包括零售业、金融服务业、出版业和银行业在内的各种行业设计开发了多个大规模、基于 Web 的系统。您可以通过以下方式与 Matt 联系:mailto:mmannion@claritycon.com。
Jon Rauschenberger 是 Clarity Consulting Inc. 的合伙人和技术主管,他经常出席各种会议(如 Microsoft Tech*Ed、VBITS、Comdex 和 DevDays)并发表演讲。Jon 还是 MSDN 芝加哥地区的区域主管。您可以通过以下方式与 Jon 联系:mailto:jrausch@claritycon.com。