VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - VB5中远程数据库的访问
发表评论(0)作者:不详, 平台:VB6.0+Win98, 阅读:10123, 日期:2001-07-05
VB5中远程数据库的访问
作者:许蔓舒
---- 在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