在上一篇文章 中,我介绍了即将对 ADO.NET 的 DataSet 类及相关类(例如 DataSet、DataTable 和 DataView)进行的更改及改进。所有这些类都是 Microsoft .NET Framework 基类库的一部分。
在本文中,我将重点介绍从 Microsoft Visual Studio 2005 开发环境中使用这些类以及衍生类进行开发的问题。本文特别讨论了对 Visual Studio 2005 生成的类型化的 DataSet 类和新的类型化的 TableAdapter 类所做的更改。本文还介绍了一些设计器和工具,它们为开发以数据为中心的应用程序功能提供了极大的灵活性和效率。为了解释不同的概念和功能,我将逐步介绍开发人员在实现应用程序的数据部分时通常会经历的过程。本文中的代码示例使用 Northwind 数据库,该数据库是 Microsoft SQL Server(及 MSDE)7.0 和 2000 附带的示例数据库。
Visual Studio 2005 引入了项目的数据源概念。数据源表示可供应用程序使用的数据。这些数据不一定来自数据库,用来定义数据源的“数据源配置向导”允许您从三个不同的来源获得数据:
1. |
数据库 - 可以是基于服务器的数据库,例如 SQL Server 或 Oracle;也可以是基于文件的数据库,例如 Aclearcase/" target="_blank" >ccess 或 SQL Server Express。Visual Studio 可以自动生成类型化的 DataSet 和其他类,并将它们添加到您的项目中。 |
2. |
对象 - 具有公共属性的任何对象都可以作为数据源,不需要实现任何特殊的接口。 |
3. |
Web 服务 - 通过 Web 服务创建数据源将创建一些与 Web 服务返回的数据类型相对应的对象。 |
数据源的用途包括两方面。首先,它作为一种方法,使指定、设计和生成强类型的类(用于表示应用程序的数据)变得更容易。其次,它提供了一种灵活但统一的机制,可以快速创建丰富且功能强大的 WinForm 和 WebForm 用户界面。阅读本文后,就会了解此过程是多么快速、简单和灵活。
在本文中,我们将重点介绍如何创建数据库 (DataSet) 数据源,以及如何在 WinForm 应用程序中使用它们。但是,记住以下两点很重要:
• |
创建数据源后,不管它的数据来自何处,使用它的方式都是相同的。也就是说,就像您可以轻松(且图形化)地将基于数据库的数据源绑定到一个网格或一组控件一样,实际上来自 Web 服务或自定义业务对象的数据也是如此。 |
• |
数据源以相同的方式进行定义,不管它们将要用在 WinForm 应用程序还是 WebForm 应用程序中。不同的数据提供程序还可以抽象化,所以如果只使用 DataSet 和 TableAdapter 提供数据访问,要更改实际的数据库,只需更改连接字符串并重新生成类即可。 |
类型化的 DataSet 和 TableAdapter
一个数据库数据源是一个强类型的 DataSet 与一对或多对强类型的 DataTable 和 TableAdapter 的组合。类型化的 DataSet 并不是一个新概念,我们曾在 Visual Studio 2002/2003 中讨论过它。类型化的 DataSet 是一个生成的类,是从 .NET Framework 的一般 DataSet 类衍生来的,但具有已定义的架构以及特定于该架构的属性和方法。同时,对于 DataSet 中的每个表,还生成了特定于该 DataSet 的三个附加衍生类:DataTable、DataRow 和 DataRowChangeEvent。每个类都为相关的表提供了特定的架构、属性和方法。例如,如果我定义一个基于 Northwind Employees 表的数据源,最后会生成以下类:
• |
NorthwindDataSet |
• |
EmployeesDataTable |
• |
EmployeesDataRow |
• |
EmployeesRowChangeEvent |
这四个类组成了类型化的 DataSet。在 Visual Studio 2005 中,还会生成第五个类,即名为 EmployeesTableAdapter 的类型化的 TableAdapter 类,我们稍后会进行讨论。当然,如果您动态定义查询,则不能生成类型化的 DataSet,而需要使用标准的 DataSet。
为什么非要使用类型化的DataSet 呢?除了强迫您事先仔细考虑数据架构的问题,而不是只“随便想想”之外,类型化的 DataSet 还提供了以下几个具体的优点:
1. |
DataSet、DataTable、DataRow 和 RowChangeEvent 特定于要处理的架构。 |
2. |
表、列和关系是作为命名属性提供的,而不是作为一般的集合元素。 |
3. |
作为第 (2) 条的结果,您可以从 Visual Studio 代码编辑器中获得全部的 IntelliSense 和语句完成支持。 |
4. |
同样作为第 (2) 条的结果,使编译时类型检查成为可能(例如,可以在编译时而不是运行时捕获字段名称拼写错误)。 |
5. |
代码更简洁、可读性更强,不会出现这样的代码: country = dsNorthwind.Tables ("Employees").Rows (row) ("Country")相反,代码应是: country = dsNorthwind.Employees (row).Country |
最基本的是,类型化的 DataSet 提供的设计时和编译时帮助不仅可以大大减少最初的开发时间,还可以大大减少调试和稳定应用程序所需的时间。
而 TableAdapter 对 Visual Studio 2005 来说则是一个全新的概念。它隐含的意思是,强类型的 TableAdapter 是标准 DataAdapter 的强类型的等价物。您使用 TableAdapter 连接数据库并对该数据库执行查询(或存储过程),然后用数据填充相关的 DataTable。每个 DataTable-TableAdapter 对简称为一个 TableAdapter。
注意:在 2004 年 12 月的 CTP 中,DataTable-TableAdapter 对被称为数据组件。但是,Visual Studio 已不再使用此术语,以后的版本中只会将该对称为 TableAdapter。本文只使用术语 TableAdapter。
TableAdapter 实质上是标准 DataAdapter 的包装程序,它具有以下几个优点:
• |
同一个 TableAdapter 类可用于多个表单或组件中,使查询/命令的任何更改都能自动反映在所有实例中。这与现状是不同的,现在,访问数据库的每个组件都必须具有自己单独配置的 DataAdapter。这使 DataTable 和 DataAdapter 之间的同步更容易实现。 |
• |
TableAdapter 使您可以轻松地为一个给定的 DataTable 定义多个命令,而不必使用多个 DataAdapter(或手动编写的切换代码)为一个 DataTable 定义多个查询/命令。 |
• |
填充命令具有可读(友好)的名称,而且 TableAdapter 包含的代码能够自动将所有参数的类型和值信息填充到这些命令方法中。您不用再担心如何传递提供程序特定的数据类型(例如 SqlInt)。 |
一个简单的代码片断将有助于说明这些功能。在 Visual Studio 2002/2003 中,即使使用类型化的 DataSet,使用两个参数执行一个简单查询的代码对查询来说也很重要:
SELECT FirstName, LastName from Employees WHERE Country = @country AND City = @city我们必须编写如下所示的代码:
Me.SqlAdapter1.SelectCommand.Parameters ("@country").value = Me.CountryListbox.SelectedValue.Trim() Me.SqlAdapter1.SelectCommand.Parameters ("@city").value = Me.CityTextbox.Text.Trim() Me.SqlAdapter1.Fill (Me.NorthwindDataSet.Employees)当然,随着参数数量的增加,代码的行数也会增加。更重要的是,正确记住并键入每个参数名称的可能性大大降低。即使参数名称正确,我还需要记住该参数的数据类型。最惨的是,如果我输入了错误的字段名称或者尝试指定了错误类型的值,直到运行时才能发现这个错误!
使用 Visual Studio 2005 中的 TableAdapter,定义命令 FillByCountryAndCity 之后,我只需编写一行代码(用于传递参数值),即可在任意位置使用该命令:
Me.EmployeesTableAdapter.FillByCountryAndCity ( _ Me.NorthwindDataSet.Employees, Me.CountryListbox.SelectedValue.Trim(), _ Me.CityTextbox.Text.Trim() )请务必注意,我们不仅是从一个 TableAdapter 中获取多个命名命令,而且这些命令是强类型的。这意味着在 Visual Studio 中编写代码时,我们可以获得全部的 IntelliSense,能够将这些命令视为 TableAdapter 的方法。我们还可以对这些命令的参数进行编译时类型检查,还可以获得带有方法和参数类型定义的工具提示以帮助我们处理各种情况。TableAdapter 可以有多个方法,用来执行不同的命令并接受不同的参数。我们将在稍后创建示例表单时进一步介绍 TableAdapter。
入门 - 创建数据源
在本文中,我们将创建一个表单,用来显示 Northwind 数据库中每个订单的订单信息。打开一个新的 Visual Basic WinForm 项目后,首先要做的是在该项目中添加一个新的数据源(我们将使用 Visual Basic 逐步介绍此过程,但所有内容同样适用于 C#)。
添加数据源的步骤:
1. |
从 Visual Studio 主菜单的 Data(数据)菜单项中选择 Show Data Sources(显示数据源),以显示 Data Sources(数据源)窗口(如果尚未显示)。 |
2. |
在 Data Sources(数据源)窗口中,单击 Add New Data Source(添加新数据源)工具栏按钮。将启动 Data Source Configuration Wizard(数据源配置向导),该向导合并了 DataAdapter Configuration Wizard(DataAdapter 配置向导)的大多数功能与 Visual Studio 2002/2003 中的 DataSet 生成工具。 |
3. |
如果您的 Visual Studio 版本仍然包含向导的 Welcome(欢迎)页面,请选择“下一步”。将显示 Choose a Data Source Type(选择数据源类型)页面。 |
4. |
选择 Database(数据库)。 |
5. |
选择 Next(下一步)。将显示 Choose Your Data Connection(选择您的数据连接)页面。 |
6. |
选择 New Connection(新建连接)。将显示 Add Connection(添加连接)对话框。 |
7. |
输入连接 SQL Server 或 MSDE 实例及 Northwind 数据库所需的信息。 |
8. |
选择 OK(确定)关闭该对话框。 |
9. |
请注意,连接字符串现在被保存为设置属性,可以通过以下字符串进行访问: My.Settings.NorthwindConnectionString在 C# 中,该字符串应为: VSDataSets.Properties.Settings.Default.NorthwindConnectionString; |
10. |
选择 Next(下一步)。将显示 Choose Your Database Objects(选择您的数据库对象)页面。 |
11. |
请注意,您可以从 Tables(表)、Views(视图)、Stored Procedures(存储过程)或 Functions(函数)中进行选择。 展开 Tables(表)节点,然后选择 Orders 和 Order Details 表。我们将使用表中的所有列,但您可以只选择您的应用程序需要的那些列。 |
12. |
选择 Finish(完成)退出向导。 |
图 1 显示了生成的 Data Sources(数据源)窗口,其中的 Order Details 表已展开以显示表中的所有列。