2

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

我有一个 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. 我通过修改和修复“Connect”连接字符串断开并重新连接了关联的 TableDef。Access声称它重新连接正常。

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

4

4 回答 4

1

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

老实说,我不明白为什么你没有收到错误。UPDATE我认为在事务中尝试使用dbForceOSFlushwithCommitTrans可能很有用。至少它可能会强制您的代码在遇到该问题时知道该错误。

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
于 2013-04-11T21:10:25.910 回答
1

我从来没有遇到过像你描述的那样的问题,但我做两件事不同:

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

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

于 2013-04-10T17:20:18.303 回答
0

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

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

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

如果您有我的问题并打算使用此解决方案,使用的GetDataPath函数通过CurrentDb.TableDefs获取链接表的位置

于 2013-04-11T20:22:50.943 回答
0

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

我按照上面 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 时丢失任何数据。

于 2016-02-08T08:29:05.530 回答