Access VBAを掌握せよ:DAOとADOの境界線で「事故らない」ためのアーキテクチャ論
Access開発において、DAO(Data Access Objects)とADO(ActiveX Data Objects)のどちらを使うべきか。この問いに対し、「ローカルはDAO、外部はADO」という教科書通りの回答だけで満足しているなら、あなたのシステムは潜在的なパフォーマンスの爆弾を抱えていると言わざるを得ません。
真のアーキテクトは、単に「何を使うか」ではなく、「データベースエンジンのライフサイクルと、メモリ消費の性質」を見極めて設計を選択します。今回は、実務の現場でバグをゼロに近づけ、保守性を極限まで高めるための技術的知見を授けます。
—
1. なぜDAOとADOの適材適所が「絶対的な正義」なのか
DAOはAccessデータベースエンジン(ACE/Jet)にネイティブ最適化されています。一方、ADOはOLE DBプロバイダを介した汎用的なデータアクセス層です。
- DAOの強み: Access内部テーブルに対しては、物理的なデータ構造を直接操作できるため、オーバーヘッドが最小です。`Recordset`の更新効率はADOを圧倒します。
- ADOの強み: SQL Server等の外部RDBMSと通信する際、非同期処理やストアドプロシージャの呼び出し、クライアントサイドカーソルによる柔軟なデータ制御が可能です。
結論: Access内部テーブルにADOで接続する、あるいは外部接続をDAOで行うのは、高級スポーツカーで砂利道を走るようなものです。
—
2. 現場で「事故る」原因は、接続の使い回しにある
多くの初心者が犯す最大の過ちは、DAOとADOのインスタンスをプロシージャ単位でバラバラに生成・破棄することです。これにより、メモリリークや接続ロックの競合が発生します。
堅牢な設計指針:接続の抽象化
DAOの場合は`CurrentDb`を、ADOの場合はグローバルな`ADODB.Connection`オブジェクトを適切に管理してください。
—
3. プロダクションコード:保守性と堅牢性を両立させる例
以下は、実務でそのまま利用できる、エラーハンドリングを完備したテンプレートです。
DAOによるローカル操作(高速・軽量)
Public Sub UpdateLocalTable()
‘ DAOはCurrentDb経由でアクセスするのが最も安全
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
‘ dbOpenTableを使うことで、インデックスを最大限に活用可能
Set rs = db.OpenRecordset(“T_Master”, dbOpenTable)
On Error GoTo ErrorHandler
db.BeginTrans ‘ トランザクションでデータの整合性を担保
With rs
.Index = “PrimaryKey”
.Seek “=”, “TargetID”
If Not .NoMatch Then
.Edit
!Status = “Processed”
.Update
End If
End With
db.CommitTrans
CleanExit:
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
db.Rollback
MsgBox “エラー発生: ” & Err.Description
Resume CleanExit
End Sub
ADOによる外部SQL Server接続(堅牢・スケーラブル)
Public Sub ExecuteSQLServerCommand()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
‘ 接続文字列は環境変数や設定テーブルから読み込むこと
conn.ConnectionString = “Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;”
conn.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = conn
‘ ストアドプロシージャ実行を推奨(SQLインジェクション対策)
cmd.CommandText = “sp_UpdateCustomerStatus”
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter(“@ID”, adInteger, adParamInput, , 100)
cmd.Execute
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
—
4. アーキテクトからの助言:パフォーマンスを極めるために
1. トランザクションの範囲を最小化せよ:
トランザクション内での処理が長いと、他のプロセスをブロックし、デッドロックの原因となります。`BeginTrans`と`CommitTrans`の間に、ユーザー入力を待つような処理は絶対に記述してはいけません。
2. Recordsetのカーソルタイプを理解せよ:
ADOで外部DBに接続する際、`adOpenStatic`や`adLockReadOnly`を適切に使い分けるだけで、ネットワーク負荷は劇的に下がります。単にデータを表示するだけなら、サーバーサイドカーソルに拘る必要はありません。
3. クリーンアップの徹底:
VBAのオブジェクトは、スコープを抜けてもメモリを即座に解放するとは限りません。`Set obj = Nothing`を明示的に行い、異常終了時にも確実に実行される設計(上記コードの`CleanExit`)を標準化してください。
まとめ
DAOとADOの使い分けは、単なる好みの問題ではありません。「Accessというプラットフォームをどう制するか」という設計思想そのものです。
まずは、既存のコードを見直してください。もし`CurrentDb`を頻繁に`Set`していたり、不必要なADO接続をローカルテーブルに対して行っているなら、そこが改善の余地です。これらを徹底するだけで、あなたの開発するツールは、泥臭いスクリプトから、堅牢な業務アプリケーションへと進化します。
次回の記事では、これらの接続層をより抽象化した「データアクセスレイヤーの構築」について深掘りします。期待していてください。
