Visual Studio 2005 以丰富的向导让数据访问的设置大幅简化,通过新增的“数据源(Data Sources)”窗口和“数据源配置向导(Data Source Configuration Wizard)”的帮助,你可以快速地设计、创建相关的对象,如 DataConnector、Typed DataSet、TableAdapter等,并完成应用程序设置。
我们就以简单的程序编写来示范这些新功能。一开始先以 Visual Studio 2005 创建一般 Visual Basic.NET 程序语言的 Windows 项目,在设计环境默认的情况下可能没有显示“数据源”窗口,你可以通过主菜单“数据(Data)”-“显示数据源(Show Data Sources)”选项打开如图12-26所示 的“数据源”窗口:

图12-26 设置数据源(Data Source)的窗口
你可以点选在窗口中间的“添加新数据源(Add New Data Source)”连接,或是左上角的“添加新数据源(Add New Data Source)”小按钮。接着要选择所使用的数据源类型,如图12-27所示:

图12-27 通过向导选择所要使用的数据源类型
如图所示,用来定义数据源的“数据源配置向导”对话框允许你从三种不同的来源获取数据:
1. 数据库(Database):来自关系数据库服务器的数据,例如 SQL Server 或 Oracle等,但也可以是来自文件数据库,例如 Access 或 SQL Server Express。当通过向导一步步设置完毕后,Visual Studio 2005 会自动对应你所选择的数据库内的对象,创建 Typed DataSet 和其他相关的类。
2. Web 服务(Web Services):将 Web 服务当作数据源,创建与 Web 服务返回的数据类型相对应的类。
3. 对象(Object):凡具有公共属性(Public Property)的对象类都可以当作数据源,不需要实现任何特殊的界面或方法。
一旦选取了数据源后,不管是上述三种的哪一种,都集成在 DataSet 架构下,然后我们在项目中操作数据的方法是一致的(例如通过 ADO.NET 相关的类操作数据,或是以提供数据绑定(Data Binding)的控制项来显示与使用数据),让数据源与数据使用逻辑分开,这是蛮不错的一个设计方式。
若整个应用程序的数据源都在 DataSet 和 TableAdapter 等类的隔绝下,不管是 Window Form 的应用程序类型还是 Web Form 的应用程序类型,若日后需要更改数据源,则可直接改变数据连接,并在重新通过工具新建相关的类后,不必再修改其后的程序商业逻辑。
我们在此选择数据库类型(在后文中也将示范用对象当作数据源),按下“下一步(Next)”后,若曾经设置过数据连接,则会有如图12-28的选择画面:

图12-28 选择曾经设置过的连接信息
若没有设置过连接,或是既有的连接不可用而点选图12-28 中的新建连接按钮,接着会出现连接设置的对话框如图12-29所示。在这个版本终于有 .NET 正宗的 SqlClient 可以选择 J,不像以往的版本总是在设置 OLE DB for SQL Server 的数据连接。
继续后,新建连接的设置细节画面如图12-30 所示:
向导设置的下一步会将连接属性存放到应用程序设置文件(app.configure)中,因此会问你存放设置的名称。接着会询问你所要采用的数据库内的对象,画面如图12-31所示:

图12-29 选择数据源的格式

图12-30 设置数据库的连接属性
在图12-31的画面中,勾选完所要使用的对象后,按下“完成(Finish)”按钮完成数据源的设置,这时 Visual Studio 2005 会自动帮我们创建 Typed DataSet 类,以及访问该数据表的 TableAdapter 对象。整个设计环境如图12-32所示:

图12-31 选择数据库内的对象

图12-32 通过“数据源配置向导”建立的 Dataset 与 TableAdapter 对象定义
由于上述的步骤,Visual Studio 2005 自动创建 Typed DataSet 和 TableAdapter 两种类,我们就先简单介绍一下这两个类的运行原理:
一个数据库数据源是以一个 Typed DataSet 与一个以上的 Typed DataTable 和 TableAdapter 等类的组合。Typed DataSet 并不是这一版所提出的新概念,在 Visual Studio 2002/2003 中就已经存在。Typed DataSet 是一般 DataSet 类的衍生类,但具备预先定义好对应数据库对象的属性和方法。
同时,对于 DataSet 中的每个数据表,还创建了特定于该 DataSet 的三个附加衍生类:DataTable、DataRow 和 DataRowChangeEvent。每个类都为相关的数据表提供了特定的数据字段 Schema、属性和方法。例如,如果我们在范例中定义一个基于 Northwind Customers 数据表的数据源,会创建以下类:
dsCustomers
CustomersDataTable
CustomersRow(定义在 CustomersDataTable 类的后方)
CustomersRowChangeEvent(定义在 CustomersRow 类的后方)
上述四种类组成 Typed DataSet。在 Visual Studio 2005 中,还会创建第五种类: CustomersTableAdapter 类,用以维护不同的数据表。在图12-32中放在各数据表的最下方区域。当然,如果是程序动态定义了查询语法,则不能使用 Typed DataSet,而需要使用一般的 DataSet 类。
而使用 Typed DataSet 类有什么好处呢?除了强迫事先仔细考虑数据架构外,Typed DataSet 还提供了以下的优点:
DataSet、DataTable、DataRow 和 RowChangeEvent 等相关对象类都特定于要处理的数据 Schema。
数据表、字段和它们彼此间的关系都是以数据库内相关对象的名称来命名属性的,而不只是一般的集合元素。因此在 Visual Studio 程序编写环境中可通过 IntelliSense 提示来自动完成程序语句。
也因为上述的设计,在编译时期就可检查类 (例如在编译时期而不是执行时期才发现字段名称写错)。
代码更简洁、可读性更强。若用 Typed DataSet,不需要这样的广用程序代码:
country = dsNorthwind.Tables ("Employees").Rows (intRow) ("Country")
相反地,上述程序代码的编写方式应该如下:
country = dsNorthwind.Employees (intRow).Country
基本上 Typed DataSet 在设计编译时提供的帮助不仅可以减少初期的开发时间,还可以减少测试和稳定应用程序所需的时间。
而Visual Studio 2005 所提供的 TableAdapter 则是全新的概念。Typed TableAdapter 与标准的 DataAdapter 有相同的功能。使用 TableAdapter 类连接数据库并执行查询或修改数据,然后将数据记录赋予到相关的 DataTable。每个 DataTable - TableAdapter 类对简称为一个 TableAdapter。
TableAdapter 类实际上是 Visual Studio 2005 自动帮你创建的,继承自 Component 类,但包装了 DataAdapter、Connection、Command 等类,它具有以下的优点:
同一个 TableAdapter 类可用在多个表单或组件中,若更改查询命令将能自动反映在所有使用该类的地方。这与 .NET Framework 1.1/VS.NET 2003 不同,2005 中查询数据库的每个组件都具有自己单独配置的 DataAdapter。这使得 DataTable 和 DataAdapter 之间的同步更容易实现。
TableAdapter 让你可以为特定的 DataTable 定义多个 SQL 命令,而不必使用多个 DataAdapter。
实际操作的命令更具有可读性,且 TableAdapter 包含的程序代码能够自动将所有参数的类型和值的信息填充到这些命令方法中。您不用再担心如何传递提供程序特定的数据类型(例如 SqlInt)。
以实例来说,若在 VS 2002/2003 中取得的数据集合带有参数,例如我们要取得某个国家/城市内的客户数据,则查询的 SQL 语法如下:
SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM dbo.Customers
WHERE Country LIKE @Country AND City LIKE @City
通过 SqlDataAdapter 取得数据并放入到 Typed DataSet,以往的程序写法如下:
adpCust.SelectCommand.Parameters ("@Country").value = txtCountry.Text.Trim()
adpCust.SelectCommand.Parameters ("@City").value = txtCity.Text.Trim()
adpCust.Fill (dsCustomer.Customers)
在 VS 2005 新的设计环境下,可以通过鼠标右键直接点选设计环境的数据表,选择加入 Query 选项,如图12-33 所示:

图12-33 针对数据源添加访问数据的查询语法
在接下来的“TableAdapter 查询配置向导”的“选择命令类型”画面勾选使用 SQL 表达式,并按“下一步”按钮。“选择查询类型”画面勾选“返回数据列的 SELECT”选项,并在指定 SQL Select 表达式画面的对话框中输入上述的 SQL 查询语法,最后赋予创建 TableAdapter 的 Fill 和 GetData 两个方法的名称,在此命名为 FillByCountryCity 和 GetDataByCountryCity,因此设置完成的画面如图12-34所示:

图12-34 加入取得数据的自定义 TableAdapter
在 VS 2005中通过这个定制的 TableAdapter ,可以简化整个数据提取的程序语法如下:
Me.CustomersTableAdapter.FillByCountryCity(Me.DsCustomers.Customers, _
txtCountry.Text.Trim(), txtCity.Text.Trim())
你可以看到整个函数在包装 SQL 查询语法时,直接用参数来对应 SQL 语法所需的参数,让程序编写更直观。
当从左方的“数据源”窗口将 Customers 数据表拖曳到 Form 的设计环境中时,Visual Studio 2005 会自动帮你创建所需的对象,整体画面如图12-35 所示:

图12-35 Visual Studio 2005 在拖曳数据表到 Form 后自动完成的对象设置
而 Visual Studio 2005 实际在 Form 中会为我们加入以下两段程序代码,首先是在 Form 装载时自动赋予数据给 DataSet 内的数据表,让 Form 上的 DataGridView 对象有数据可以显示:
'VS 2005 自动加入的程序代码,在 Form 装载的时候自动赋予 Dataset 内 Table 数据
Me.CustomersTableAdapter.Fill(Me.DsCustomers.Customers)
接着是赋予画面顶端的 DataNavigator 控制项的 Save Data 按钮更新数据回数据源的程序代码:
'VS 2005 自动为 DataNavigator 的 Save Data 按钮所加入的程序代码
Me.Validate()
Me.CustomersBindingSource.EndEdit()
'通过环境自动建立的 TableAdapter 对象将数据更新回数据源
Me.CustomersTableAdapter.Update(Me.DsCustomers.Customers)
这个程序到此可以直接编译并执行,你会发现在 VS 2005 要创建一个添加、修改、删除和浏览数据的应用程序变得非常简单。另外,我们可以在表单中加入让用户输入国家和城市的文本框,名称为 txtCountry、txtCity。设计画面如图12-36 所示:

图12-36 通过过滤条件取回想要的数据记录
图12-36 所加入的确定按钮,其 Click 事件的程序代码如下:
Me.DsCustomers.Customers.Clear()
Me.CustomersTableAdapter.FillByCountryCity(Me.DsCustomers.Customers, _
txtCountry.Text.Trim(), txtCity.Text.Trim())
在上面的范例中,VS 2005 还会自动帮我们在用户介面上加一个类似录影/音机的控制项 BindingNavigator,并加入相关的程序代码,让你不需要编写程序就可以直接操控记录。BindingNavigator 其实是一个预先放置好控制项的 strip 控制项,并通过 BindingSource 属性绑定到 BindingSource 实例,默认提供 BindingNavigator 控制项上的按钮来浏览记录。也因为BindingNavigator 是一个 strip 控制项,你可以重新设置默认放在其 strip item 内的控制项,或是新增 strip item 放置其他的控制项。
当数据源被拖曳到表单中以 DataGridView 或文本框等控制项显示时,VS 2005 设计环境会自动将 BindingSource 和 BindingNavigator 组件一并加入到表单中。这帮我们包装了在数据绑定(data-bound)控制项和数据源间的 BindingManager,BindingManager 需要完成以下的工作:
管理数据控制项和数据源间的多个绑定关系。
保持绑定控制项和其下数据源间的同步,有任何一方变动时数据要更新到另一方。
保持所有绑定的控制项显示的是当前记录。
复杂的数据绑定控制项,如 DataGridView 知道如何访问使用 BindingManager 来执行上述的各点功能。但简单的绑定控制项,如绑定TextBox 的 Text 属性到某个列表(list)的数据字段,则不会支持 BindingManager。若要完成绑定,以往你需要手动编写程序代码来使用 BindingManager。 例如绑定到某个数据库内的数据表,将显示的记录移到下一条,需要使用如以下的程序代码:
‘移到下一笔记录
Dim binding As Binding = CompanyNameTextBox.DataBindings("Text")
Dim manager As BindingManagerBase = binding.BindingManagerBase
manager.Position = manager.Position + 1
为了避免这些麻烦,可以通过 BindingSource 来包装 BindingManager ,并提供一个简单的访问界面。与其他复杂的数据绑定控制相似的是,你可以通过设置 BindingSource 的 DataSource 和 DataMember 属性来访问数据源。这其实会让 BindingSource 访问到数据源的 binding manager,而通过 BindingSource 的界面,你可以更容易使用数据绑定。BindingSource 会通过 reflection 的机制来分析底层的数据源结构,然后决定需要在其 IBindingList 接口提供哪些数据字段。这代表你可以将任何对象的属性绑定,例如 TextBox 控制项的 Text 属性,直接绑定到 BindingSource,所以当从“数据源”窗口拉入以TextBox 控制项字段显示的数据内容时,可以通过属性窗口的 (DataBindings) 属性下的 (高级) 属性打开如下的对话框,此时会发现 Visual Studio 2005 已经自动帮我们将 TextBox 控制项的 Text 属性绑定到 BindingSource 的 CustomerID 字段。画面如图12-37 所示:

图12-37 设置控制项的属性与 BindingSource 的字段创建数据绑定
这会让上述移动记录的程序代码简化如下:
‘移到下一笔记录
Me.CustomersBindingSource.MoveNext()
在 Data Sources 窗口中,我们可以定义各字段在设置到 Form 时要以什么样的控制项显示(如图12-38)。例如,我们定义 CustomerID 字段是主键,只能读取,因此改用 Label 控制项来显示。

图12-38 设置各字段在 Form 中要以什么样的控制项显示
而在 Form 引用数据表时,也可以通过数据表所提供的下拉式选单来设置是以 DataGridView(默认采用这个控制项)来显示数据表,还是以多个控制项来显示(如图12-39所示)。

图12-39 设置 Form 显示数据表时要采用的方式
当设置完要以“详细数据”的方式显示后,再将数据表拖曳到 Form 中,会显示如图12-40所示的画面:

图12-40 以多个控制项显示数据表各字段的内容
我们再把 Data Sources 窗口中的 Orders 数据表拖曳到 Form 中,以默认的 DataGridView 控制项显示,很容易就完成了 Master Detail 数据编修的 Form。画面如图12-41所示:

图12-41 设置 Master Detail 编辑画面
在设置完画面后,你需要自行进入到程序编写的环境为保存的按钮加入以下的程序代码,让用户不管是更新主要数据还是细节数据都可以更新回数据库:
Me.OrdersBindingSource.EndEdit()
Me.OrdersTableAdapter.Update(Me.DsCustomers.Orders)
如此便可完成的数据维护的应用程序,还算简单吗J
ADO.NET 2.0 就介绍到此,希望能让你对通过它集成到 SQL Server 2005 中的数据访问有整体的认识。然而它的功能当然不仅止于此,你可以到 MSDN 网站上查找更多关于 ADO.NET 2.0 的高级技巧及其相关的知识。





