【入門編】DAOのトランザクション処理中に発生する「予期せぬ中断」への備え – Access VBA解析バイブル

スポンサーリンク
スポンサーリンク

データの整合性を守る「盾」:DAOトランザクションと鉄壁のエラーハンドリング

こんにちは。Access VBAの世界へようこそ。

マクロの記録から一歩踏み出し、「自分でコードを書いて制御したい」と思い立ったあなた。その意欲こそが、エンジニアとしての第一歩です。素晴らしいですね。

しかし、プログラムが複雑になればなるほど、避けて通れない「恐ろしい問題」に直面することになります。それは、「処理の途中でエラーが起き、データが中途半端に書き換わってしまう」という事態です。

例えば、銀行の振込処理を想像してください。「Aさんの口座から1万円引く」処理は成功したのに、その直後の「Bさんの口座に1万円足す」処理でエラーが起きて止まってしまったら……? Aさんの1万円は、世界のどこにも存在しない幽霊のようなデータになってしまいます。

これを防ぐための技術が「トランザクション」です。今日は、プロの開発者が必ず使いこなしている、DAOを用いたトランザクション処理と、絶対にデータを壊さないためのエラーハンドリングの極意を伝授します。

ここをクリアすれば、あなたのAccessアプリの信頼性は、プロの領域へと一気に引き上げられるはずですよ。

1. トランザクションとは「全か無か」の約束

トランザクションとは、一言で言えば「複数の処理を一つのまとまりとして扱うこと」です。

エンジニアの世界では、これを「原子性(Atomicity)」と呼びます。
「全ての処理が完璧に成功するか、さもなくば、最初から何もしていなかった状態に戻るか」のどちらかしかない、という極めて厳格なルールです。

  • Commit(コミット): 全ての処理が成功したので、変更を確定させる。
  • Rollback(ロールバック): 途中でエラーが起きたので、全ての変更を取り消して元の状態に戻す。

この「Commit」と「Rollback」を正しく制御することが、データベースの整合性を守るための唯一の手段なのです。

2. 【実践】鉄壁のトランザクション・テンプレート

それでは、実際に現場でそのまま使える「黄金のテンプレート」を見ていきましょう。
DAO(Data Access Objects)を使用して、複数のテーブルを更新するシナリオを想定しています。

Option Compare Database
Option Explicit

''' <summary>
''' 複数のテーブルを更新するトランザクション処理の例
''' </summary>
Public Sub ExecuteSafeTransaction()
    ' --- 1. オブジェクトの宣言 ---
    Dim db As DAO.Database
    Dim ws As DAO.Workspace ' トランザクション管理にはWorkspaceが必要!
    
    ' --- 2. エラーハンドリングの設定 ---
    ' エラーが発生したら「ErrorHandler」ラベルへジャンプするように指示
    On Error GoTo ErrorHandler

    ' --- 3. 初期設定 ---
    ' DAOのデフォルトのWorkspaceを取得
    Set ws = DBEngine.Workspaces(0)
    Set db = CurrentDb

    ' --- 4. トランザクションの開始 ---
    ' ここから「Commit」か「Rollback」されるまでの一連の処理が「一つの塊」になります
    ws.BeginTrans
    Debug.Print "トランザクションを開始しました。"

    ' --- 5. メインの業務ロジック(ここを書き換えて使用) ---
    
    ' 例:在庫テーブルを更新
    db.Execute "UPDATE T_Inventory SET StockCount = StockCount - 1 WHERE ProductID = 101", dbFailOnError
    Debug.Print "在庫を減らしました。"

    ' (ここで何らかの予期せぬエラーが発生したと仮定...)
    ' 例:売上テーブルにデータを追加
    db.Execute "INSERT INTO T_Sales (ProductID, SaleDate) VALUES (101, Date())", dbFailOnError
    Debug.Print "売上を記録しました。"

    ' --- 6. 全て成功した場合の確定処理 ---
    ' ここまでエラーなく到達できれば、全ての変更がデータベースに書き込まれます
    ws.CommitTrans
    MsgBox "処理が正常に完了しました。", vbInformation, "成功"

' --- 7. 終了処理(正常終了・エラー終了共通) ---
ExitProc:
    ' オブジェクトの解放(メモリリークを防ぐために重要!)
    Set db = Nothing
    Set ws = Nothing
    Exit Sub

' --- 8. エラーハンドリング(エラー発生時にジャンプ) ---
ErrorHandler:
    ' エラーが発生した場合、まずRollbackを試みる
    ' wsがセットされている(=トランザクション中である)ことを確認
    If Not ws Is Nothing Then
        ws.Rollback
        Debug.Print "エラーが発生したため、ロールバックを実行しました。"
    End If

    ' エラー内容をユーザーに通知(実務ではログ出力なども行う)
    MsgBox "致命的なエラーが発生しました。処理を中断し、データを元に戻しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "エラー内容: " & Err.Description, vbCritical, "エラー発生"

    ' 終了処理へ向かう
    Resume ExitProc
End Sub

3. アーキテクトの視点:なぜこのコードなのか?

ただコードを写すだけではもったいない。なぜこの書き方が「正解」なのか、その理由(重み)を理解しましょう。

① `Workspace` オブジェクトの重要性

ここが最大の落とし穴です。多くの初心者は `Database` オブジェクトに対してトランザクションをかけようとしますが、DAOにおいてトランザクションの管理権限を持っているのは `Workspace` です。
`ws.BeginTrans` と書くことで、そのWorkspaceが管理するすべてのデータベース操作が、一つのユニットとして束ねられます。

② `dbFailOnError` オプションの徹底

`db.Execute` を使う際、必ず末尾に `dbFailOnError` を付けてください。
これがないと、例えば「型が違う」「制約違反」といったエラーが起きても、VBAはエラーを吐かずに「無視して次の行へ」進んでしまいます。トランザクションの「全か無か」という哲学を貫くためには、エラーを確実にキャッチするこのオプションが必須です。

③ `On Error GoTo` と `Resume ExitProc` の構造

エラーが起きた時、いきなりプログラムを終了させてはいけません。
1. Rollback でデータを守る
2. Cleanup (Set Nothing) でメモリを掃除する
3. Exit で安全に抜ける

この「後片付けのフロー」を確立することが、システムを長時間安定して動かすためのプロの作法です。

4. よくある失敗と回避策

開発中に陥りやすい「罠」をまとめておきます。

失敗パターン 起こる現象 回避策
Rollbackを忘れる データベースがロックされたままになり、他のユーザーが操作できなくなる。 `ErrorHandler` 内で必ず `ws.Rollback` を実行する。
エラー処理の中でさらにエラーが出る プログラムがクラッシュし、不完全な状態で止まる。 `ErrorHandler` 内の処理は極力シンプルにし、複雑なロジックを書かない。
変数のスコープミス `ws` が `ErrorHandler` から見えず、Rollbackできない。 `ws` はプロシージャの先頭で宣言し、適切な範囲(スコープ)で管理する。

まとめ:整合性を守れるエンジニアへ

トランザクションとエラーハンドリングをマスターすることは、単に「エラーを防ぐ」ことではありません。「ユーザーの大切なデータを、いかなる状況下でも守り抜く」という責任を果たすことなのです。

最初は少し記述量が多く感じるかもしれません。しかし、このテンプレートを自分の「型」として体に叩き込んでください。そうすれば、どれほど複雑な業務ロジックを組むことになっても、あなたは自信を持って「このシステムは安全だ」と言えるようになります。

さあ、次のステップへ進みましょう。あなたのコードが、より強固で美しいものになることを応援しています!

タイトルとURLをコピーしました