【问题标题】:Detecting disconnected Microsoft Access linked table检测断开连接的 Microsoft Access 链接表
【发布时间】:2013-04-10 15:59:16
【问题描述】:

底线是我想尽可能优雅地处理网络断开连接。

我有一个 Microsoft Access 应用程序,它使用链接表将 UI 与数据“分离”。因此,有两个 msaccess 数据库文件(一个 UI 和另一个数据)。这两个数据库都在我们的内部网络上,并且 UI 使用链接表链接到数据。这是一个非常标准的设置。

代码中只有一个位置需要这种优雅的断开逻辑(即执行 SQL UPDATE 时)。我认为这就像一些错误处理一样简单。但是,Microsoft Access 有时会假装成功

这是进入我的世界的窗口:

On Error GoTo ErrorHandler:
Call CurrentDb.Execute("UPDATE [Thing] SET [Length]=5 WHERE [ID]=1;", dbFailOnError)
On Error GoTo 0

   ...(continued code)...

ErrorHandler:
    fSuccess = False
    Resume Next

我启动应用程序,拔掉我的网线(不,wifi 没有打开),但有时错误处理永远不会发生,即使它实际上并没有更新!澄清一下,当断开连接时,我希望此更新失败,并且我想检测它!

我一直在尝试解决像这样对我撒谎的 Access。越努力越绝望:

  1. 我注意到的第一件事是如果我使用调试器单步调试,它将正确可靠地失败。不过,这对我没有帮助。
  2. 我试过检查更新操作的RecordCount,但是当它假装成功时,它确实设置为1!
  3. 我已尝试执行后续的 SELECT 语句以查看 UPDATE 是否真的发生了。不过,即使我在 UPDATE 中输入了一个随机数,访问也会返回正确的结果。
  4. 我查看了 Access 对象(如 CurrentDb 和 TableDefs),寻找任何可靠的迹象表明它在“离线模式”或“缓存模式”下工作。我找不到任何指标。这对我有很大帮助。
  5. 无论连接还是断开,链接表的 RecordCount 始终为 -1。
  6. 我已断开并重新连接关联的 TableDef,方法是修改和修复“连接”连接字符串。 Access 声称它重新连接正常。

我不明白我看到的行为。 MSAccess 是否在连接数据的某些缓存下运行?如果是这样,为什么它只有时起作用?如果他们真的有一些复杂的离线缓存模式,为什么没有在任何地方记录呢?很遗憾,我不允许在工作中喝酒。

【问题讨论】:

  • +1 最后一句。 (但是,问题的其余部分也值得 +1。)
  • 你使用的是dbFailOnError参数吗?
  • 是的。抱歉不清楚,我简化了例子,因为完整的代码有点麻烦。

标签: ms-access ms-access-2007


【解决方案1】:

我从来没有遇到过跟你描述的完全一样的问题,但我做了两件事不同:

  1. 我总是先声明Dim cdb As DAO.DatabaseSet cdb = CurrentDB,然后再声明cdb.Whatever。有时CurrentDB.Whatever 的行为会有所不同。

  2. 我总是这样做cdb.Execute "SQL statement", dbFailOnError。我认为这可能与您的问题特别相关。

【讨论】:

  • 感谢您的想法。我已经在做这两件事了,但为了示例的简单性,我作弊了。
【解决方案2】:

也许,正如您所建议的,数据库引擎针对内存中存在的[Thing] 表的缓存版本执行UPDATE,目的是稍后将其写入磁盘。但是,如果发生了这种情况,似乎 Access 在稍后尝试执行磁盘写入时应该会引发错误。

老实说,我不明白为什么您没有收到错误消息。我认为在事务中尝试UPDATEuse dbForceOSFlush with CommitTrans 可能会有用。至少它可能会强制一个错误,您的代码可以捕捉到您何时遇到该问题。

Dim strUpdate As String
Dim db As DAO.Database
Dim ws As DAO.Workspace

strUpdate = "UPDATE [Thing] SET [Length]=5 WHERE [ID]=1;"
Set ws = DBEngine(0)
Set db = CurrentDb
ws.BeginTrans
db.Execute strUpdate, dbFailOnError
ws.CommitTrans dbForceOSFlush
ws.Close
Set db = Nothing
Set ws = Nothing

【讨论】:

  • 这是个好主意。我不知道这个冲洗的想法。当我有能力的时候,我会试试这个。目前,我的检查网络访问的技巧已经到位,并且很难重新创建。
【解决方案3】:

到目前为止,我想出的最好办法是检查我是否可以通过网络访问底层数据库文件。

Public Function EnsureNetworkConnected() As Boolean

    Dim sDataPath As String
    sDataPath = GetDataPath

    Dim fFileExists As Boolean
    Dim objFileSystem As New FileSystemObject
    fFileExists = objFileSystem.FileExists(sDataPath)
    If Not fFileExists Then
        ' Huh.
    End If

    EnsureNetworkConnected = fFileExists

End Function

如果更新语句“假装”成功,我会使用此函数再次检查它。这是一个脆弱的 hack。

如果您有我的问题并打算使用此解决方案,使用的 GetDataPath 函数通过 CurrentDb.TableDefs

获取链接表的位置

【讨论】:

    【解决方案4】:

    我意识到这个帖子有点老了,但我现在陷入了与描述相同的情况并想添加我的两个便士。

    我按照上面 HansUp 的建议添加了“dbForceOSFlush”。当我拔下网线(并关闭 WiFi)时,我仍然没有收到错误

    Dim wrk As DAO.Workspace
    Dim dbs As DAO.Database
    Set wrk = DBEngine(0)
    Set dbs = CurrentDb
    wrk.BeginTrans
    dbs.Execute "aJudges", dbFailOnError
    wrk.CommitTrans dbForceOSFlush
    Debug.Print "AppendJudger " & Time()
    TimerCounter = 0
    

    另一个观察是,当我拉网络时,第一次尝试执行查询需要很长时间(比如 30 秒),然后所有查询运行顺利,只是连接丢失,因此在关闭 Access 时丢失任何数据.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-23
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多