6

私のアプリケーションでは、次のことを行います。

  1. Jet/ADO と VB6 を使用して Access データベース (.mdb) を開く
  2. テーブルをクリアして新しいデータを再入力する
  3. データベースを閉じる
  4. 新しいデータで何かを行う別のプロセスを開始します。

問題は、2 番目のプロセスが新しいデータを見つけられない場合があることです。テーブルが空の場合もあれば、RecordCount > 0 の場合もありますが、EOF が真であり、MoveFirst または MoveNext を実行できません。一言で言えば、あらゆる種類の奇妙なことです。

私の現在の回避策は、データベースを閉じてから 2 番目のプロセスを開始するまでに遅延を追加することです。

  • ここで何が起きてるの?
  • それについて何かできることはありますか?(別のデータベースを使用する以外に)
4

3 に答える 3

7

単なる推測ですが、Jet エンジンが読み取りキャッシュと遅延書き込みを備えていることが原因である可能性があります。

Jet 4.0 および ADO 2.1 でマルチユーザー カスタム カウンターを実装する方法

「Microsoft Jet には、PageTimeout ミリ秒 (デフォルトは 5000ms = 5 秒) ごとに更新される読み取りキャッシュがあります。また、メイン処理とは別のスレッドで動作する遅延書き込みメカニズムも備えているため、変更を非同期的にディスクに書き込みます。これら 2 つメカニズムはパフォーマンスの向上に役立ちますが、高い同時実行性が必要な特定の状況では、問題が発生する可能性があります。」

この記事では、Jet の RefreshCache メソッドを使用し、Jet OLEDB:Transaction Commit Mode を 1 ミリ秒に設定することを提案しています (Jet の DAO に対する ADO の利点の 1 つは、レジストリの値を変更せずにこの設定を変更できることです)。

PS 代わりに「Jet」に言及するように Access データベース (.mdb) を編集し、「Jet」タグも使用することを検討する必要があります。そうしないと、これらのことについて厄介な特定の SO ユーザーからコメントを受け取ることになります :)

于 2009-01-28T10:06:56.197 に答える
3

このMicrosoft Knowledge Base の記事では、その方法について説明しています。

サンプルコード付きの抜粋です。コードは 1 つのプロセスから 2 つの接続を使用するため、読み取り部分を 2 番目のプロセスにプルする必要があります。

  1. ライターは、データを書き込む前に、ADO の Connection.BeginTrans を使用してトランザクションを開始する必要があります。
  2. ライターは、データベースを更新してから、トランザクションをコミットする必要があります (ADO の Connection.CommitTrans を使用)。
  3. リーダーは、データの読み取りを試行する前に、その接続を渡す JRO.JetEngine.RefreshCache を呼び出す必要があります。

JRO.JetEngine は、Microsoft Jet And Replication Objects 2.1 Library への参照を 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
于 2009-01-28T10:21:28.353 に答える
-1

最初のプロセスはMDBが開いている唯一のプロセスであるため、ファイルにデータを書き戻すのは少し面倒です。プロセスを終了した後でも、OSが未処理のページを書き戻すまでに遅延が発生する可能性があります。これは、プロセスが完了したことを通知した後に発生する可能性があります。

私の推奨事項は、Accessの使用をやめ、代わりにSQL Server2008Expressを使用することです。

于 2009-01-28T09:17:53.160 に答える