Почему моя база данных Access не обновилась, когда я прочитал ее из другого процесса? - PullRequest
5 голосов
/ 28 января 2009

В своем приложении я делаю следующие вещи:

  1. Открыть базу данных Access (.mdb), используя Jet / ADO и VB6
  2. Очистить и заново заполнить таблицу новыми данными
  3. Закрыть базу данных
  4. Запустите другой процесс, который что-то делает с новыми данными.

Проблема в том, что иногда второй процесс не может найти новые данные. Иногда таблица пуста, иногда RecordCount> 0, но EOF имеет значение true, и я не могу сделать MoveFirst или MoveNext. В двух словах: все виды странных вещей.

Мой текущий обходной путь - добавление задержки между закрытием базы данных и запуском второго процесса.

  • Что здесь происходит?
  • Могу ли я что-нибудь с этим сделать? (Кроме использования другой базы данных)

Ответы [ 3 ]

7 голосов
/ 28 января 2009

Просто предположение, но я могу быть из-за того, что движок Jet имеет кеш чтения и ленивые записи:

Как реализовать многопользовательские пользовательские счетчики в Jet 4.0 и ADO 2.1

"Microsoft Jet имеет кэш-память чтения, которая обновляется каждые миллисекунды PageTimeout (по умолчанию 5000 мс = 5 секунд). Он также имеет механизм отложенной записи, который работает в отдельном потоке для основной обработки и, таким образом, записывает изменения на диск асинхронно . Эти два механизма помогают повысить производительность, но в определенных ситуациях, требующих высокого параллелизма, они могут создавать проблемы. "

В статье предлагается использовать метод Jet RefreshCache и установить для Jet OLEDB: Transaction Commit mode значение 1 миллисекунду (одно преимущество ADO над DAO для Jet заключается в том, что вы можете изменить этот параметр без изменения значения в реестре).

P.S. вам следует подумать о том, чтобы отредактировать базу данных Access (.mdb), чтобы вместо нее упомянуть 'Jet', а также использовать тег 'Jet', в противном случае вы получите комментарий от определенного пользователя SO, который привередлив в этих вещах:)

3 голосов
/ 28 января 2009

В этой статье базы знаний Майкрософт объясняется, как это сделать.

Вот выдержка с примером кода. Код использует два соединения из одного процесса, поэтому вам нужно вставить часть чтения во второй процесс.

  1. Автор должен начать транзакцию, используя ADO Connection.BeginTrans, до записи данных.
  2. Автор должен обновить базу данных, а затем зафиксировать транзакцию (используя ADO's Connection.CommitTrans).
  3. Читатель должен вызвать JRO.JetEngine.RefreshCache, передавая соединение, перед попыткой чтения данных.

Обратите внимание, что JRO.JetEngine включен путем добавления ссылки на библиотеку Microsoft Jet и объекты репликации 2.1 в ваш проект VB.

    Sub SyncReadDemo()
    Dim conn1 As New ADODB.Connection
    Dim conn2 As New ADODB.Connection
    Dim rs As New ADODB.recordset
    Dim JRO As New JRO.JetEngine
    Dim strConnect As String
    Dim i As Long


  ' Set up our connection string (requires a database named c:\db1.mdb).
    strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\db1.mdb"

    ' Open connection 1 and drop and re-create test table.
    conn1.CursorLocation = adUseServer
    conn1.Open strConnect
    On Error Resume Next
    conn1.Execute "drop table tmpTest", , _
        adExecuteNoRecords + adCmdText
    On Error GoTo 0
    conn1.Execute "create table tmpTest (id long)", , _
        adExecuteNoRecords + adCmdText

    ' Close connection 1 to flush the creation of table tmpTest. 
    conn1.Close

    ' Now open connection 1 and connection 2.
    conn1.Open strConnect
    conn2.Open strConnect

    ' Insert 10 records using connection 1.
    ' Note we must perform all writes inside of a transaction.
    conn1.BeginTrans
    For i = 1 To 10
        conn1.Execute "insert into tmpTest (id) values (1)", , _
            adExecuteNoRecords + adCmdText
    Next i
    conn1.CommitTrans

    ' Refresh cache for reader connection.
    JRO.RefreshCache conn2
    Set rs = conn2.Execute("select * from tmpTest", , adCmdText)

    ' Count records in our table (should be 10).
    i = 0
    While Not rs.EOF
        i = i + 1
        rs.MoveNext
    Wend
    rs.Close

    MsgBox "Read " & i & " records using different connections."

    conn1.Close
    conn2.Close

End Sub
0 голосов
/ 28 января 2009

Поскольку первый процесс является единственным процессом с открытым MDB, он может быть немного ленив в отношении записи материала обратно в файл. Даже после того, как вы завершите процесс, может произойти задержка, пока ОС записывает оставшиеся страницы, и это может произойти после того, как процесс дал сигнал о завершении.

Моя рекомендация: прекратить использование Access, вместо этого использовать SQL Server 2008 Express.

...