65.9K
CodeProject 正在变化。 阅读更多。
Home

ADO.NET RecordSet 库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.44/5 (15投票s)

2006年7月18日

CPOL

6分钟阅读

viewsIcon

173664

downloadIcon

2035

一个 ADO.NET recordset 类。

引言

我和大多数人一样,最初接触数据库是从 MS Access 开始的,当然,我还发现了 VBA。好吧……我曾涉猎 C、C++,以及一点 C# 和其他几种语言。我想我可以尝试一些新东西。VBA 非常易于使用和理解,我很快就开发了一个具有后端文件(数据文件)和前端(可分发界面文件)的相当复杂的数据库。起初我使用了链接表,随着数据库复杂性的增加,问题也随之而来。首先,MS Access 控制了数据,在我不想更改数据时(例如,调用移动到下一条记录命令或更改数据后简单地关闭窗体)它会记录下来。第二个问题是由于网络问题,应用程序速度下降。

得益于一种叫做 recordsets 的东西,我解决了我的问题。我在 MS Access 中构建了一个类,允许我做两件事。它允许我随意处理数据,并且非常易于使用。它还允许我使用数据的快照图像,这极大地提高了我的应用程序在网络上的速度。我创建的这个类还做了一种数据与窗体控件的伪绑定。通过这样做,我重新获得了对数据的全部控制,从而避免了“不想要的记录和数据更改”问题(如果你使用过 MS Access,你应该知道我在说什么)。但是 DAO 和 ADO recordsets 仍然相对较慢,因为它们需要持续连接。在已经很慢的网络中,同时连接数据库的三个以上用户会让数据库变得迟缓和难以使用。

于是我开始研究 ADO.NET……而我发现的东西并不令人愉快;Connections, DataAdapters, DataSets, DataTables, DataRows, DataColumns……哇哦。我头晕目眩。我问自己,是否有像 DAO 或 ADO recordset 那样容易使用的东西?我找不到任何。关于 ADO.NET 的另一件事是,大多数文章都谈论使用向导自动构建针对特定数据格式的大量代码。如果数据库结构发生变化怎么办?我该怎么办?完全重建窗体???

基于此,我开始构建这个简单的库,它模拟了一个 recordset,另一个执行伪绑定……但那是另一个故事了。

注释

我不太理解 ADO.NET。事实上,我甚至无法开始理解它提供的功能数量和所有可能性,我甚至可能在这里说一些非常愚蠢的话。

如果你在寻找一个奇迹般的解决方案……算了吧。其理念是允许你简单、基础地使用 ADO.NET 的功能。

如果你想要一个非常简单的数据库界面层,这里就是你要找的地方。

主要概念

这两个库的主要概念是充当数据库(表和关系)与界面之间的中间层。

Application Layer schematics

这样做的好处是,如果你想更改数据库文件的一些结构性东西(比如说你想将数据库技术从 MS Access 迁移到 MS SQL Server),你只需要更改中间层而无需更改整个应用程序。

另一个方面是减少了向导生成的代码量。更改自动生成的代码有时很痛苦。“我没写这个。这是什么?”

ADO.NET RecordSet 类

基本上,recordset 的工作方式类似于一个指向数组的指针。它必须提供搜索功能以及创建、删除和保存功能。例如,为了跟踪我们的位置,我们需要一个存储当前位置的整数变量。这个 `index` 是我们 recordset 的关键,根据它的值,我们将遍历数据。这些是这个类使用的一些变量

'
'Variables declared inside the class
'
Private conn As OleDb.OleDbConnection
Private dadapter As OleDb.OleDbDataAdapter
Private cmdbld As OleDb.OleDbCommandBuilder
Private select_command As OleDb.OleDbCommand
Private insert_command As OleDb.OleDbCommand
Private delete_command As OleDb.OleDbCommand
Private update_command As OleDb.OleDbCommand
Private dset As DataSet
Private dtable As DataTable
Private drow As DataRow
Private index As Long
Private newRow As Boolean
Private found As Boolean
Private SQLQuery As String
Private foundrecords_counter As Long
Private operation_finished As Boolean = False

要使用 recordset,我们必须像使用 DAO 或 ADO recordset 一样进行操作。

  • 打开连接
  • 打开 recordset
  • 执行所有需要的操作
  • 关闭 recordset

打开连接

ADO.NET `Recordset` 类有一个 `Connection` 函数,它只是存储数据库文件的路径和要使用的提供程序(以及您认为有用的其他参数),并通过打开和关闭连接来测试连接。

Function Connection(ByVal constr As String)
    Try
        conn.ConnectionString = constr
        conn.Open()
        conn.Close()
        Connection = True
    Catch ex As Exception
        MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical + _
               MsgBoxStyle.ApplicationModal + MsgBoxStyle.OkOnly, _
               "ADO.NET RecordSet Library Error")
        Connection = False
    End Try
End Function

打开和关闭 recordset

当 recordset 打开时,`index` 变量设置为 0(recordset 的开头),否则设置为 -1(BOF - 文件开头,表示没有记录被指向)。`SQLstr` 指示表的 SQL 查询(例如:“SELECT * FROM OurTable”)。`fields` 用于检索表中列的名称(见下文)。`newRow` 用作标志(见下文)。

要打开 recordset,我们只需这样做

Function OpenRecordSet(ByVal SQLstr As String)
    Try
        dadapter = New OleDb.OleDbDataAdapter(SQLstr, conn)
        dadapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
        dadapter.MissingMappingAction = MissingMappingAction.Passthrough
        dadapter.Fill(dset)
        fields = dset.Tables(0).Columns
        If dset.Tables(0).Rows.Count() = 0 Then
            index = -1
        Else
            index = 0
        End If
        newRow = False
        OpenRecordSet = True
    Catch ex As Exception
        MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical + _
               MsgBoxStyle.ApplicationModal + MsgBoxStyle.OkOnly, _
               "ADO.NET RecordSet Library Error")
        OpenRecordSet = False
    End Try
End Function

要关闭 recordset,我们只需这样做

Function CloseRecordSet() As Boolean
    Try
        dset.Dispose()
        dadapter.Dispose()
        conn.Dispose()
        CloseRecordSet = True
    Catch ex As Exception
        MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical + _
               MsgBoxStyle.ApplicationModal + _
               MsgBoxStyle.OkOnly, "ADO.NET RecordSet Library Error")
        CloseRecordSet = False
    End Try
End Function

所以要使用这个类,我们只需要这样做

  • 创建并初始化我们的变量(例如命名为“`rs`”)
  • rs.Connection(连接参数在此处)
  • rs.OpenRecordSet(定义我们表的 SQL 查询)

这很棒,但我该如何在 recordset 中检索/设置值?

让我们看看如何做到这一点。

检索/设置 recordset 的值

要返回/设置 recordset 中字段的值,我们创建一个名为 `FieldValue` 的属性,并指示要返回/设置的列的名称或索引。例如,此属性的重载实现之一如下所示

Property FieldValue(ByVal columnName As String)
    Get
        Try
            FieldValue = dset.Tables(0).Rows(index).Item(columnName)
        Catch ex As Exception
            MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical + _
                   MsgBoxStyle.ApplicationModal + MsgBoxStyle.OkOnly, _
                   "ADO.NET RecordSet Library Error")
        End Try
    End Get
    Set(ByVal Value)
        Try
            If newRow Then
                drow.Item(columnName) = Value
            Else
                dset.Tables(0).Rows(index).Item(columnName) = Value
            End If
        Catch ex As Exception
            MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical + _
                   MsgBoxStyle.ApplicationModal + MsgBoxStyle.OkOnly, _
                   "ADO.NET RecordSet Library Error")
        End Try
    End Set
End Property

如您所见,`newRow` 标志在这里用于识别我们是在修改现有记录还是在创建新记录。

很好,但我该如何浏览 recordset?

让我们看看如何进行导航……

浏览 recordset

recordset 的导航和搜索是通过 `index` 的值来完成的。所以如果我们想在 recordset 中来回移动,我们只需操作该变量。

要导航 recordset,我们构建 `Move<direction>` 函数集。

这是 `MoveFirst` 示例

Sub MoveFirst()
    index = 0
End Sub

Recordset 上的标志

标志是 recordset 的一个重要方面。它们为您提供了 recordset 在导航或搜索后的状态指示。这些指示通常是布尔值,告诉您,例如,是否已到达 recordset 的末尾,或者搜索(`Find<word>` 函数集)是否成功。

`BOF` 标志就是这样一个例子。当达到 recordset 的开头时(在 recordset 之前,没有数据),此标志为 true

例如,如果您连续执行 `MovePrevious` 命令并超过第一个位置,您可能会看到此标志为 true。

ReadOnly Property BOF() As Boolean
    Get
        If index < 0 Then
            BOF = True
        Else
            BOF = False
        End If
    End Get
End Property

示例

我相信这个例子非常直接且易于理解。

它只是使用 recordset 的一些命令和一些标志,向您展示了如何使用此库以及 recordset 的功能有多么简单。

结论

在本文中,您已经了解了如何创建一个简单的 recordset 类来浏览数据库中的数据。至于窗体中的数据绑定,嗯……那将是下一章。

希望这有帮助。祝好!

© . All rights reserved.