Microsoft® Office 提供了多种存储和管理数据的功能和工具,例如,数据访问对象 (DAO)、ActiveX® 数据对象 (ADO)、Microsoft Word 邮件合并、Microsoft Excel Web 查询、Microsoft Query、数据访问页、Microsoft Access 数据项目、Office 数据连接、Office 数据链接等等。而 Microsoft .NET 平台则提供了其他的数据访问功能和工具,例如,ADO.NET、.NET 数据连接和数据库项目。
在本月的专栏中,我将介绍如何使用 Microsoft Visual Studio® .NET、Microsoft Visual Basic® .NET,特别是如何使用 ADO.NET 来解锁和管理 Microsoft Access 数据。
既然 Office 已经提供了一系列数据访问功能和工具,为什么不利用 Office 来管理它自己的数据呢?当然,在许多情况下,您可能希望使用适合某个特定数据任务的内置 Office 功能和工具。然而,ADO.NET 提供了一种添加数据连接和编写数据解决方案代码的统一方法,这种方法不同于 Office 中的多个数据入口点和数据访问库。
如果您愿意,仍然可以在 Visual Studio .NET 和 Visual Basic .NET 中调用 ADO 功能。但鉴于以下原因,与 ADO 相比,ADO.NET 在许多方面都是更好的数据访问解决方案。
当然,如果希望利用 .NET 中的诸多新功能,就应该使用 .NET 数据访问功能和工具。有关 .NET 平台的详细信息,请参阅以前的专栏 Introducing .NET to Office Developers(英文)。
图 1 显示了使用 ADO.NET 时要用到的主要对象。
图 1:ADO.NET 对象模型中的主要对象(来源:Inside .NET Managed Providers [英文])
这些对象包括:
作为参考,在使用 ADO 的 Office Visual Basic for Applications (VBA) 中,可以通过以下方法打开罗斯文示例 Access 数据库,将数据从 Products 表复制到 Recordset 对象,并报告记录集中第一条数据记录的某些数据:
' Office VBA 和 ADO 代码 - ADOCode.bas。 Public Sub ADOExample() ' 首先设置对 ADO 库的引用。 Dim objConn As ADODB.Connection Dim objRS As ADODB.Recordset Set objConn = New ADODB.Connection objConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "User ID=Admin;" & _ "Data Source=C:\Program Files\Microsoft " & _ "Office\Office10\Samples\Northwind.mdb" objConn.Open Set objRS = objConn.Execute("SELECT * FROM Products") objRS.MoveFirst MsgBox Prompt:=objRS.Fields("ProductName").Value & ", " & _ objRS.Fields("UnitsInStock").Value objRS.Close objConn.Close End Sub
如果您以前在 ADO 中进行过编码,则此 ADO 代码是非常简单的:
作为比较,下面是一些用于控制台应用程序的 Visual Basic .NET 示例代码,使用 ADO.NET 执行大体相同的操作,但它并不将数据放入记录集,而是由一个 ADO.NET 数据读取器保持与数据的连接:
' Visual Basic .NET 和 ADO.NET 代码 - ADONETCode.vb。 ' 使用连接的 ADO.NET 数据访问。 ' 控制台应用程序。 Imports System.Data.OleDb Module Module1 Sub Main() ' 首先设置对 System.Data.dll 的引用。 Dim objConn As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "User ID=Admin;" & _ "Data Source=C:\Program Files\Microsoft" & _ "Office\Office10\Samples\Northwind.mdb") objConn.Open() Dim objCmd As New OleDbCommand _ ("SELECT * FROM Products", objConn) Dim objDataReader As OleDbDataReader = objCmd.ExecuteReader objDataReader.Read() Console.Write(objDataReader.Item("ProductName") & ", " & _ objDataReader.Item("UnitsInStock")) End Sub End Module
下面是该代码的工作方式:
Imports System.Data.OleDb
有助于减少访问对象或对象的成员时所需的工作量。例如,尽管可以在 ADO 中编写 ADODB.Recordset
代码,但通常并不这样做,因为已经引用了 ADODB 库。同样,尽管可以在 ADO.NET 中编写 System.Data.OleDb.OleDbConnection
代码,但如果已经导入了与 OleDbConnection 对象关联的名称空间 System.Data.OleDb(假设我们已预先设置了对 System.Data.dll 的引用),也就不需要进行编码。
下面是另一段 Visual Basic .NET 示例代码,执行与前面的 ADO.NET 示例相同的操作。但在这一示例中,数据将被复制到 ADO.NET 数据集,然后断开与数据库的连接:
' Visual Basic .NET 和 ADO.NET 代码 - ADONETCode.vb。 ' 使用断开连接的 ADO.NET 数据访问。 ' 控制台应用程序。 Imports System.Data.OleDb Module Module1 Sub Main() ' 首先设置对 System.Data.dll 的引用。 Dim objConn As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "User ID=Admin;" & _ "Data Source=C:\Program Files\Microsoft" & _ "Office\Office10\Samples\Northwind.mdb") objConn.Open() Dim objAdapter As New OleDbDataAdapter _ ("SELECT * FROM Products", objConn) Dim objDataSet As New DataSet() objAdapter.Fill(objDataSet) With objDataSet.Tables("Table").Rows(0) Console.Write(.Item("ProductName") & ", " _ & .Item("UnitsInStock")) End With End Sub End Module
下面是此代码与前一 ADO.NET 示例的区别:
虽然您可能希望在 Office VBA 中使用 ADO.NET 的新功能,但目前还不能这样做。这是因为,如果运行 RegAsm.exe(.NET Frameworks SDK 中的程序集注册工具)将 System.Data.dll 注册为 COM(Office VBA 基于此技术),然后尝试从 Office 引用生成的类型库文件,则不会在 Office Visual Basic 的对象浏览器中显示任何成员。这是因为 COM 不能识别核心的私有 ADO.NET 成员和参数化的构造函数。因此,至少在目前,还只能继续在 Office VBA 中使用 ADO。
Visual Studio .NET 提供了许多便利工具用于访问 Office 数据,包括创建可重复使用的数据连接、数据库项目以及数据表单向导。
数据连接允许您一次性定义数据库连接的详细信息,然后在多个解决方案中重复使用该信息。下面的示例介绍如何在 Visual Studio .NET 中创建可重复使用的数据连接:
这样就有了一个可以添加到 Visual Studio .NET 项目的可重复使用的数据连接。
下面基于这些步骤给出一个示例,说明如何创建 ADO.NET 对象,这些对象能够与 Server Explorer(服务器资源管理器)窗口中的现有数据连接进行交互操作:
注意:在 Visual Studio .NET Beta 2 中,不会显示 Fill Dataset(填充数据集)按钮,以便生成实际填充 Dataset 对象的代码。可能需要手动向 Form_Load 或 Page_Load 事件添加代码,如下所示:Me.OleDbDataAdapter1.Fill(DataSetName11)
。
下面的示例介绍如何在 Windows 窗体中添加数据网格,并绑定到前一示例中生成的现有数据集:
Me.OleDbDataAdapter1.Fill(DataSetName11)
。
提示:要在 Server Explorer(服务器资源管理器)窗口中没有现有数据连接的情况下创建 ADO.NET 对象,请执行以下步骤:
Visual Studio .NET 数据库项目允许您快速创建面向数据库的解决方案。下面的示例介绍如何在 Visual Studio .NET 中创建数据库项目:
Visual Studio .NET 数据表单向导允许您快速连接到数据库,并生成简单的用户界面,用于显示数据并与数据进行交互。要使用数据表单向导,请执行以下步骤:
注意:请确保将新数据表单设置为启动表单,方法如下:在 Project(项目)菜单中,单击 Properties(属性)。展开 Common Properties(通用属性)文件夹,单击 General(常规),在 Startup object(启动对象)列表中选择该数据表单,然后单击 OK(确定)。
注意:请确保将 DataSet1 中的数据绑定到数据表单,这可以通过向数据表单的 Load 事件插入以下代码来实现:Me.OleDbDataAdapter1.Fill(objDataSet1)
为了向您演示更多的 ADO.NET 代码,在本月专栏的最后,我将介绍几个在 ADO.NET 中创建的扩展的代码示例。
很多时候,您只是希望简单地浏览数据,而并不需要在数据间来回浏览,也不需要更改数据(我们将此称为“流水数据”)。ADO.NET 的 DataReader 对象是专门为此设计的。下面是我编写的一段示例代码,可以逐个读取连接的数据库中的所有选定数据:
' Visual Basic .NET 代码。 ' 控制台应用程序。 ' 引用: ' System ' System.Data ' System.XML Imports System.Data.OleDb ' 用于 OleDb 对象。 Imports Microsoft.VisualBasic.ControlChars ' 用于 CrLf 常量。 Module Module1 Sub Main() ' 创建并初始化 OleDbConnection、OleDbCommand ' 和 OleDbDataReader 对象。 Dim objConn As New _ OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "User ID=Admin;" & _ "Data Source=C:\Program Files\Microsoft" & _ "Office\Office10\Samples\Northwind.mdb") objConn.Open() ' 执行命令并将数据读取器附加到 ' 所选数据。 Dim objCmd As New OleDbCommand("SELECT * FROM Products", _ objConn) Dim objReader As OleDbDataReader = objCmd.ExecuteReader ' 读取数据并列出值。 Call ReadData(objReader) End Sub Public Sub ReadData(ByVal objReader As OleDbDataReader) ' 目的:列出给定数据读取器的数据值。 ' 接受:objReader - 数据读取器。 Dim intField As Integer ' 行中的当前字段。 Dim intColumn As Integer ' 当前列的名称。 Dim blnColumns As Boolean = False ' 列名称是否已 ' 列出。 With objReader ' 一次读取一行,直至文件末尾。 Do While .Read = True For intField = 0 To .FieldCount - 1 ' 首先列出列名称。 If blnColumns = False Then For intColumn = 0 To .FieldCount - 1 If intColumn = .FieldCount - 1 Then Console.Write(.GetName(intColumn) & _ CrLf) Else Console.Write(.GetName(intColumn) & _ ", ") End If Next intColumn ' 只列出一次列名称。 blnColumns = True End If ' 列出当前行中每个字段的值。 If intField = .FieldCount - 1 Then Console.Write(.Item(intField) & CrLf) Else Console.Write(.Item(intField) & ", ") End If Next intField Loop End With ' 暂停,以便用户在控制台窗口中查看数据。 Console.Write("按任意键继续...") Console.Read() End Sub End Module
下面是该代码的工作方式:
Imports System.Data.OleDb
)有助于减少访问对象或对象的成员时所需的工作量。类似地,对 OleDbConnection、OleDbCommand 和 OleDbDataReader 对象进行声明和初始化,以分别代表数据库连接、数据记录和记录游标。此代码的真正核心是 ReadData 子例程。
ADO.NET 的 DataSet 对象是为断开连接的数据而设计的。您可以在一个数据集中模拟整个数据库的结构和数据,包括表、行、列、字段,甚至关系。处理完数据后,可以使数据集中的数据与原始数据库中的数据同步。下面是我编写的一段示例代码,可以逐个读取断开连接的数据集中的所有数据。
' Visual Basic .NET 代码。 ' 控制台应用程序。 ' 引用: ' System ' System.Data ' System.XML Imports System.Data.OleDb ' 用于 OleDb 对象。 Imports Microsoft.VisualBasic.ControlChars ' 用于 CrLf 常量。 Module Module1 Sub Main() ' 创建并初始化 OleDbDataAdapter 和 DataSet 对象。 Dim objAdapter As New OleDbDataAdapter _ ("SELECT * FROM Products", _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "User ID=Admin;" & _ "Data Source=C:\Program Files\Microsoft" & _ "Office\Office10\Samples\Northwind.mdb") Dim objDataSet As New DataSet() ' 将所选数据复制到数据集。 objAdapter.Fill(objDataSet) ' 列出数据集中的数据值。 Call ListData(objDataSet) End Sub Public Sub ListData(ByVal objDataSet As DataSet) ' 目的:列出给定数据集的数据值。 ' 接受:objDataSet - 数据集。 Dim objTable As DataTable Dim intRow, intColumn As Integer ' 数据集中可能包含有多个表。 For Each objTable In objDataSet.Tables With objTable Console.Write("表" & _ .TableName "中的数据" & ":" & CrLf) ' 首先列出列名称。 For intColumn = 0 To .Columns.Count - 1 If intColumn = .Columns.Count - 1 Then Console.Write(.Columns(intColumn).ColumnName _ & CrLf) Else Console.Write(.Columns(intColumn).ColumnName _ & ", ") End If Next intColumn ' 按行列出数据... For intRow = 0 To .Rows.Count - 1 ' ...然后按字段列出每行中的数据。 For intColumn = 0 To _ .Rows(intRow).ItemArray.Length - 1 If intColumn = _ .Rows(intRow).ItemArray.Length - 1 Then Console.Write(.Rows(intRow). _ ItemArray(intColumn) _ & CrLf) Else Console.Write(.Rows(intRow). _ ItemArray(intColumn) & ", ") End If Next intColumn Next intRow End With Next objTable ' 暂停,以便用户在控制台窗口中查看数据。 Console.Write("按任意键继续...") Console.Read() End Sub End Module
下面是该代码的工作方式:
Imports System.Data.OleDb
)有助于减少访问对象或对象的成员时所需的工作量。类似地,对 OleDbDataAdapter 和 DataSet 对象进行声明和初始化,分别代表数据库与数据集之间的适配器以及数据集。OleDbAdapter 对象的 FillData 方法将数据库中的数据复制到数据集。此代码的核心是 ListData 子例程。
有关 ADO.NET 的更多信息,请参阅以下内容:
与以往一样,请定期访问 Office 开发人员中心(英文),以查找有关 Office 解决方案开发的信息和技术文章。