VB 程序设计

10个成员

VB5中远程数据库的访问

发表于 2016-12-25 2758 次查看
---- 在VB5.0 中, 用Microsoft Jet 数 据 库 引 擎 和 数 据 访 问 对 象DAO(Data Access Object) 可 以 创 建 功 能 强 大 的 客 户/ 服 务 器 应 用 程 序。 对 远 程 数 据 库 的 访 问 是 开 发 这 类 应 用 程 序 的 关 键 环 节, 本 文 将 介 绍 在VB5.0 中 用DAO 通 过Miscrosoft Jet 数 据 库 引 擎 访 问 远 程 数 据 库 的 方 法。

---- 用DAO 访 问 远 程 数 据 库 大 体 上 可 以 通 过 三 步 来 实 现, 即 数 据 连 接、 数 据 处 理 和 断 开 连 接。 下 面 主 要 介 绍 数 据 连 接 和 数 据 处 理 的 具 体 操 作。

---- 一、 数 据 连 接

---- DAO 一 般 通 过 链 接 远 程 表 的 方 式 来 进 行 数 据 连 接。 这 样, 数 据 虽 然 驻 留 在 远 程 数 据 源 上, 但 在 本 地 的Microsoft Jet 数 据 库 中 可 以 存 储 与 远 程 数 据 的 永 久 性 连 接, 同 时 缓 存 链 接 的 表 结 构 信 息, 从 而 在 下 一 次 访 问 该 表 时, 不 用 再 次 从 服 务 器 中 检 索 这 些 结 构 信 息, 加 快 了 连 接 速 度。 一 旦 链 接 了 一 个 表, 该 链 接 便 会 保 留 在 各 会 话 期 间, 直 到 连 接 断 开。 链 接 远 程 表 的 具 体 操 作 是:

用OpenDatabase 方 法 打 开 将 要 包 含 该 链 接 的 本 地Microsoft Jet 数 据 库

用CreateTableDef 方 法 在 该 数 据 库 中 创 建 一 个 新 的TableDef 对 象

将TableDef 对 象 的Connect 属 性 设 置 为 一 个 合 法 的 连 接 字 符 串, 标 识 要 访 问 的 远 程 数 据 库 类 型、 数 据 文 件 的 路 径 以 及 用 户 名 和 远 程 数 据 源 密 码 等。

将TableDef 对 象 的SourceTableName 属 性 设 置 为 远 程 数 据 库 中 要 访 问 的 表 的 名 称。

添 加TableDef 对 象 到TableDefs 集 合 中。
----     实 现 链 接 远 程 表 操 作 的 过 程 如 下:

Public Sub LinkTable(strDB As String, strRoDB As String,
strCn As String, strTdf As String, _
          linkTdfName As String)
   Dim linkTdf As New TableDef
   Set dbs = OpenDatabase(strDB)
   linkTdf.Name = linkTdfName
100
   tempTable = UCase(linkTdf.Name)
   For i = 0 To dbs.TableDefs.Count - 1
     If UCase(dbs.TableDefs(i).Name) = tempTable Then
       If MsgBox(linkTdfName + " 已存在,是否删除 ?", _
      vbQuestion + vbYesNo) = vbYes Then
         dbs.TableDefs.Delete linkTdf.Name
         Exit For
       Else: MsgBox "重新输入新表名"
       linkTdfName = InputBox(" 新表名")
       GoTo 100
       End If
     End If
   Next i
Set linkTdf = dbs.CreateTableDef
(linkTdfName)  '链接远程表
   linkTdf.Connect = ";database=" + strCn
   linkTdf.SourceTableName = strTdf
   dbs.TableDefs.Append linkTdf
End Sub

---- 上 述 过 程 用 来 实 现 远 程 表 的 连 接, 它 有5 个 参 数, 其 中strRoDB 是 要 访 问 的 远 程 数 据 库 名( 包 括 路 径);strTdf 是 该 数 据 库 中 的 表 名;strDB 是 要 链 接 的 本 地 数 据 库( 包 括 路 径);linkTdfName 是 本 地 数 据 库 的 一 个 新 表 名, 用 来 建 立 远 程 表 的 链 接;strCn 是 指 定 连 接 信 息 的 字 符 串。 需 要 特 别 注 意 的 是, 除 了 在 访 问 远 程Microsoft Jet 数 据 库 时, 连 接 字 符 串 要 以 分 号(;) 开 头 外, 指 定 连 接 信 息 的 字 符 串 都 必 须 以 所 访 问 的 远 程 数 据 库 类 型 开 头。DAO 可 以 访 问 的 远 程 数 据 源 有 以 下 三 类:

Microsoft Jet 数 据 源, 如:Access 数 据。

IISAM( 可 安 装 的 索 引 化 顺 序 访 问 方 法) 格 式 数 据 源, 如:FoxPro、Paradox、dBASE 数 据。

ODBC 数 据 源, 如:SQL Server 数 据、Oracle 数 据。
---- 例 如: 设 网 络 服 务 器 名 为server, 共 享 目 录 为C:\Sales 的FoxPro 3.0 数 据 库, 连 接 字 符 串 应 为

---- strCn="FoxPro3.0;database=\\server\c$\Sales\Region1"

---- 此 外,DAO 通 过Microsoft Jet 数 据 库 引 擎 访 问 远 程 数 据 时, 还 可 以 用OpenDatabase 方 法 直 接 打 开 远 程 表。 在 本 地 数 据 库 中 并 未 存 储 与 远 程 数 据 源 建 立 连 接 所 需 要 的 信 息。 如 果 使 用 链 接 方 式 访 问 数 据, 则 不 必 在 每 次 会 话 开 始 时 提 供 连 接 信 息, 从 而 可 以 提 高 效 率。

---- 二、 数 据 处 理

---- 数 据 连 接 建 立 后, 可 以 用OpenRecordset 方 法 打 开 一 个 记 录 集, 并 可 用DBGrid 控 件 和Data 控 件 方 便 地 浏 览 整 个 记 录 集。 如 果 使 用 表 类 型(Table-type) 记 录 对 象, 则 对 应 的 是 一 个 实 际 存 在 的 数 据 库 表, 在 多 用 户 环 境 下, 其 它 用 户 对 数 据 的 修 改 会 立 即 反 映 到 表 中; 如 果 使 用 动 态 集 类 型(Dynaset-type) 记 录 对 象, 则 对 应 的 既 可 以 是 一 个 表 中 全 部 记 录, 又 可 以 是 一 个 查 询 的 结 果, 并 且 可 以 更 新 记 录 集 中 的 记 录; 如 果 使 用 快 照 类 型(Snapshot-type) 记 录 对 象, 则 对 应 的 可 以 是 表 中 的 全 部 记 录, 也 可 以 是 一 个 查 询 结 果, 但 不 能 进 行 记 录 的 增 加、 删 除 和 修 改 操 作。 此 外, 还 可 以 建 立 其 它 类 型 的 记 录 对 象, 如 仅 向 前 型(ForwardOnly-type) 记 录 对 象 和 动 态 型(Dynamic-type) 记 录 对 象。

---- 下 面 是 打 开 动 态 集 记 录 对 象 并 显 示 记 录 的 过 程:

Public Sub rst_display(strDB As String,
strRst As String, strForm As Form)
   Set dbs = OpenDatabase(strDB)
   Set rst = dbs.OpenRecordset(strRst, dbOpenDynaset)
   strForm!Data1.DatabaseName = dbs.Name
   strForm!Data1.RecordSource = rst.Name
   strForm!Data1.Refresh
   strForm!DBGrid1.ReBind
End Sub

---- 上 述 过 程 有 三 个 参 数, 其 中strDB 用 来 指 定 本 地 数 据 库 名( 包 括 路 径),linkTdfName 是 在 本 地 数 据 库 中 新 建 的 链 接 远 程 表 的 表 名,strForm 是 网 格 控 件 和 数 据 控 件 所 在 的 窗 体 名。 调 用 此 过 程 可 以 基 于 新 表 建 立 一 个 动 态 集 类 型 的 记 录 对 象, 并 可 在 网 格 中 浏 览 各 个 记 录。

---- 断 开 连 接 可 以 通 过 关 闭 应 用 程 序 或 设 置 连 接 超 时 来 实 现。 注 意: 如 果 对 数 据 库 对 象 使 用Close 方 法, 则 由 于 在Miscrosoft Jet 数 据 库 引 擎 内 部 缓 存 了 连 接, 实 际 上 连 接 并 未 取 消。

---- 三、 应 用 举 例

---- 以 上 介 绍 了 用DAO 访 问 远 程 数 据 库 的 具 体 操 作, 下 面 通 过 一 个 例 子 说 明 链 接 远 程 表 和 建 立 记 录 集 对 象 的 方 法。

---- 首 先 建 立 一 个 新 工 程, 在 窗 体 上 画5 个 命 令 按 钮,1 个 数 据 控 件 和1 个 数 据 网 格 控 件(DBGrid), 各 对 象 的 属 性 设 置 见 表1。


表1 窗体1对象属性设置 对象 标题(Caption) 名称(Name)
窗体 远程数据访问 Form1
命令按钮1 链接远程表 cmd链接
命令按钮2 添加 cmdAdd
命令按钮3 删除 cmdDel
命令按钮4 修改 cmdModify
命令按钮5 结束 cmdEnd
数据控件 Data1 Data1
数据网格  DBGrid1

---- 其 中DBGrid1 中 的DataSource 属 性 设 为Data1, 命 令 按 钮2,3,4 的Visible 属 性 设 为False。

---- 编 写 如 下 事 件 过 程:

----

Private Sub cmdAdd_Click() '添加记录子过程
   On Error GoTo errHandler
   With rst
  .AddNew
   For i = 0 To .Fields.Count - 1  '遍历记录集中的每个字段
   '在输入框中输入各字段的数据
.Fields(i).Value = InputBox
("输入记录信息" & vbCr + "字段名:" + .Fields(i).Name)
   Next i
   .Update
  End With
  Data1.Refresh
  DBGrid1.ReBind
errHandler:     '错误处理
   Select Case Err
     Case 3022, 3421
       MsgBox (Error + vbCr + "输入无效")
       Exit Sub
     Case Else
       Response = 0
       Exit Sub
   End Select
End Sub

Private Sub cmdDel_Click() '删除记录过程
On Error GoTo errHandler
BeginTrans     '事务处理
  With Data1.Recordset
   If .BOF And .EOF Then Exit Sub '如果没有记录,退出过程
   .Delete    '删除
   If .BOF And .EOF Then   '如果没有记录,退出过程
     Exit Sub
   ElseIf .EOF Then .MoveLast 
'如果删除的是最后一条记录,光标移至最后一记录
   Else: .MoveNext  '移至下一条记录
   End If
  End With
If MsgBox("确实要删除这一记录?",
vbQuestion + vbYesNo) = vbYes Then
   CommitTrans  '确认
   Data1.Refresh
Else
   Rollback        '撤消改动
  Data1.Refresh
End If
errHandler:      '错误处理
Select Case Err
  Case 3021  '无当前记录
   MsgBox ("无当前记录,请选择要删除的记录")
   Exit Sub
  Case Else
   MsgBox (Error)
   Exit Sub
End Select
End Sub

Private Sub cmdEnd_Click()
End     '结束应用程序
End Sub

Private Sub cmdModify_Click()
DBGrid1.AllowUpdate = True  '允许修改
End Sub

Privatev Sub cmd链接_Click()
Form1.Hide
   Form2.Show
End Sub

Private Sub DBGrid1_After
ColUpdate(ByVal ColIndex As Integer)
'数据修改后触发该事件
On Error GoTo err1
Data1.Refresh
err1:
   Select Case Err
     Case 0
       Response = 0
     Case Else
       Exit Sub
   End Select
End Sub

Private Sub DBGrid1_BeforeColUpdate(ByVal
ColIndex As Integer,
OldValue As Variant, Cancel As Integer)
'数据修改前触发该事件
On Error GoTo errHandler:
BeginTrans
If MsgBox("确实要修改这一内容?",
vbQuestion + vbYesNo) = vbYes Then
     CommitTrans
   Else
     Rollback
     Data1.Refresh
End If
errHandler:
   Select Case Err
     Case 0
       Response = 0
     Case Else
       MsgBox (Error)
       Exit Sub
   End Select
End Sub

Private Sub Form_Load()
'在窗体装入时,网格中的数据不可添加,修改
   DBGrid1.AllowAddNew = False
   DBGrid1.AllowUpdate = False
End Sub

Private Sub Form_Resize()
On Error Resume Next
  '当窗体调整时会调整网格
  DBGrid1.Height = Me.ScaleHeight
- Data1.Height - cmd删除.Height - 30
End Sub

---- 在 工 程 中 添 加 一 个 窗 体, 在 窗 体 上 画6 个 标 签,1 个 命 令 按 钮( 标 题 为" 确 认", 名 称 为cmd 确 认),3 个 文 本 框 和1 个 组 合 框 在 窗 体 的 声 明 部 份 输 入 以 下 代 码:

---- ' 声 明 窗 体 层 变 量

Dim rodbs As Database
Dim strDB As String, strRoDB
As String, strCn As String, strTdf As String
Dim linkTdfName As String

编写如下事件过程:
Private Sub cmd确认_Click()
On Error GoTo errHandler:
strDB = text2.Text '本地数据库名及路径
linkTdfName = Text3.Text
'本地数据库中新建的链接远程表的表名

   strCn = strRoDB '连接字符串
strTdf = Combo1.Text
'指定远程数据库中要访问的表
   '调用LinkTable过程
Call LinkTable(strDB,
strRoDB, strCn, strTdf, linkTdfName)
   '调用rst_display过程
   Call rst_display(strDB, linkTdfName, Form1)
   Form2.Hide
   Form1.Show
Form1.Caption =
"远程数据:" + strCn + "-" + strTdf
   '显示"添加","删除","修改"控件
   Form1.cmdAdd.Visible = True
   Form1.cmdDel.Visible = True
   Form1.cmdModify.Visible = True
errHandler:
   Select Case Err
     Case 0
       Response = 0
     Case Else
       MsgBox (Error + vbr + "重新输入")
       Exit Sub
   End Select
End Sub

Private Sub Combo1_GotFocus()
strRoDB = text1.Text 
'指定远程数据库名及路径
Set rodbs = OpenDatabase(strRoDB)
'打开远程数据库
   '删除combo1中的内容
   If Combo1.ListCount >= 1 Then
     For i = Combo1.ListCount - 1 To 0 Step -1
       Combo1.RemoveItem i
     Next i
   End If
   '把数据库中的表名加到combo1中
   For i = 0 To rodbs.TableDefs.Count - 1
     Combo1.AddItem rodbs.TableDefs(i).Name
   Next i
End Sub

 

发表回复
你还没有登录,请先登录注册