您可以使用无数种方法在 VB 和 VBNET 中处理数据这两个平台都支持诸如数组和集合之类的结构开发人员通常将自定义类包装到这些结构中就如您在 Carl Ganz 年 月的专栏中看到的那样数据独立(这可能是创建自定义数据抽象层的最大优势)允许用户在独立于数据库的情况下操作数据这不仅降低了服务器的负担还消除了维护到该数据库的开放连接的需要或是对忘记更新 RDBMS 的担心本月Carl 将分析如何同时使用 ADO 和 ADONET 来创建此类数据对象
在 VB 中OLE DB 游标服务允许您创建通常作为虚构的Recordset 的内容这些只是 ADO Recordset 对象的内存中实例Field 对象将添加到这些实例中以形成一个数据结构您需要显式创建这些 Recordset 客户端如清单 中所示默认情况下它们是在服务器端创建的您在服务器上不能有离线 Recordset
Set oRS = New ADODBRecordset
oRSCursorLocation = adUseClient
oRSCursorType = adStatic
oRSLockType = adLockBatchOptimistic
Add a few fields
With oRSFields
Append LastName adVarChar adFldIsNullable
Append FirstName adVarChar adFldIsNullable
Append HireDate adDate
End With
oRSOpen
一旦创建 Recordset您就可以用数据填充它了请注意Field 集合的 Append 方法只能用于关闭的 Recordset如果您在打开 Recordset 的 Fields 集合上或是已设置 ActiveConnection 属性的 Recordset 上调用 Append就会导致运行时错误清单 阐释了如何将数据添加到 Recordset 对象
清单 中的最后两行代码阐释了如何创建索引以使排序更加高效(通常您应通过一个提供初始排序的 SQL 命令来加载此类数据但是如果数据在网格中您可能希望允许用户通过(比如说)单击列标题来排序它)
清单 用数据填充 Recordset 对象
Populate with some data
oRSAddNew Array(LastName FirstName HireDate)_
Array(Washington George //)
oRSAddNew Array(LastName FirstName HireDate)_
Array(Adams John //)
oRSAddNew Array(LastName FirstName HireDate)_
Array(Jefferson Thomas //)
oRSUpdate
Create an inmemory index
oRSFields(LastName)Properties(Optimize)Value _
= True
Sort on first name
oRSSort = FirstName
创建 Recordset 的另一种方法涉及到离线 Recordset这只是一个 Recordset 对象它随后将连接到由于将 ActiveConnection 属性设置为 Nothing 而离线的服务器(请参见清单 )
清单 创建离线 Recordset
Dim objConnection As ADODBConnection
Dim szSQL As String
Set objConnection = New ADODBConnection
Open a connection
objConnectionConnectionString = whatever
objConnectionOpen
Instantiate a Recordset object
Set oRS = New ADODBRecordset
oRSCursorLocation = adUseClient
oRSCursorType = adOpenStatic
oRSLockType = adLockBatchOptimistic
and set the ActiveConnection property
Set oRSActiveConnection = objConnection
szSQL = SELECT LastName FirstName & _
FROM Employees & ORDER BY LastName FirstName
Open the Recordset and return the employee data
oRSOpen szSQL
Set oRSActiveConnection = Nothing
objConnectionClose
Set DataGridDataSource = oRS
使用 ADONET
ADONET 为离线数据管理提供了更强大的功能DataTable 和 DataSet 对象本身就定义为离线因此您不必执行任何操作来使它们离线从概念上来说ADONET DataTable 对象和 ADO Recordset 对象的编程创建过程非常类似如清单 中所示在本示例中我们要创建一个 DataTable 对象并向其添加列和行对象正如您将看到的那样ADONET 的方法使用了一个比基于 COM 的 ADO 所使用的更加层次化的对象模型
清单 创建 ADONET DataTable 对象
Dim oDataRow As DataRow
Dim oDataColumn As DataColumn
Dim aPrimaryKey() As DataColumn
oDS = New DataSet
Create a new DataTable oect
oEmployeeDT = New DataTable
Add an event handler for column data changes
AddHandler oEmployeeDTColumnChanged _
New DataColumnChangeEventHandler(AddressOf _
ColumnChanged)
Create primary key (PK) col and add it to the columns
collection Set init value to increment as needed
oDataColumn = New DataColumn
oDataColumnColumnName = ID
oDataColumnDataType = _
SystemTypeGetType(SystemInt)
oDataColumnAutoIncrement = True
oDataColumnAutoIncrementSeed =
oEmployeeDTColumnsAdd (oDataColumn)
PK property receives array of DataColumn objects in
case you have multicol index I prefer an ID column
aPrimaryKey() = oDataColumn
oEmployeeDTPrimaryKey = aPrimaryKey
Create the individual data columns
a€|
oDataColumn = New DataColumn
oDataColumnColumnName = Salary
oDataColumnDataType = _
SystemTypeGetType(SystemDecimal)
oEmployeeDTColumnsAdd (oDataColumn)
Here we use DataColumns Expression property to show
what a % tax on the salary will amount to
oDataColumn = New DataColumn
oDataColumnColumnName = IncomeTax
oDataColumnDataType = _
SystemTypeGetType(SystemDecimal)
oDataColumnExpression = Salary *
oEmployeeDTColumnsAdd (oDataColumn)
oDataColumn = New DataColumn
oDataColumnColumnName = HireDate
oDataColumnDataType = _
SystemTypeGetType(SystemDateTime)
oEmployeeDTColumnsAdd (oDataColumn)
This col receives the value calcd by event handler
oDataColumn = New DataColumn
oDataColumnColumnName = DaysSinceHire
oDataColumnDataType = _
SystemTypeGetType(SystemInt)
oEmployeeDTColumnsAdd (oDataColumn)
Once the columns are added add sample data
oDataRow = oEmployeeDTNewRow()
oDataRow(LastName) = Washington
oDataRow(FirstName) = George
oDataRow(Salary) =
oDataRow(IncomeTax) = True
oDataRow(HireDate) = //
oEmployeeDTRowsAdd (oDataRow)
a€|
Commit new data to the DataTable object and set
RowState values of each row to Unchanged
oEmployeeDTAcceptChanges()
Lets show the user
DataGridDataSource = oEmployeeDT
在实例化 DataTable 对象之后您就可以使用这个事件模型将事件处理程序DataColumnChangeEventHandler设置为自定义例程通过传递 ColumnChanged 例程的地址只要一个列中的数据更改您就可以执行这个处理程序在本例中我们要使用它来确定职员被雇佣以来的天数(请参见清单 )
清单 ColumnChanged 事件处理程序
Sub ColumnChanged(ByVal sender As Object _
ByVal e As DataColumnChangeEventArgs)
If eColumnColumnName = HireDate Then
eRow(DaysSinceHire) = _
DateDiff(DateIntervalDay _
eRow(HireDate) DateToday)
End If
End Sub
由于用户在网格中编辑数据添加和删除行因此每个行对象的 RowState 属性会更改以指示所作修改的类型当用户将离线数据提交到 RDBMS 时需要计算每一行来确定用户执行了何种类型的更改要完成这一操作您可以通过 GetChanges 方法检索包含所有新近添加修改和删除的行的 DataTable 对象然后循环访问这个新 DataTable 中的每个行对象并计算 RowState 属性如清单 中所示
清单 标识更改的行并保存更改
Dim oDataRow As DataRow
Dim oChangeDT As DataTable
Get DataTable with only changed rows
oChangeDT = oEmployeeDTGetChanges()
Save button s/b disabled until a change is made
If oChangeDT Is Nothing Then
Exit Sub
End If
Loop thru changed rows make db updates
For Each oDataRow In oChangeDTRows
Select Case oDataRowRowState
Case DataRowStateAdded
Insert code here
Case DataRowStateModified
Update code here
Case DataRowStateDeleted
Delete code here