2008/05/07

CurrentProject.Connectionの謎

再びAccessVBA教本ネタから。今回はADOの接続部分についてです。

Dim cn As ADODB.Connection
Dim rst As ADODB.Recordset

Set cn = CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM TB_ログ ORDER BY ログID", cn, adOpenForwardOnly, adLockReadOnly
Do Until rst.EOF
    rst.MoveNext
Loop
rst.Close
cn.Close

Set rst = Nothing
Set cn = Nothing

なんだかこのサンプルソースを見ていて違和感を感じたわけですね。違和感の部分はConnectionで、オブジェクト変数cnについて注目してください。まず、

Set cn = CurrentProject.Connection

自分自身の接続のインスタンスをSetでcnに渡している──この部分はいいでしょう。既にmdbファイルという自分自身は実体化しているわけですから、改めてNewして、インスタンスを生成する必要性は感じません。

さらにいうならば、CurrentProject──自分自身のことですから、既に接続がOpenされ済みとみなしていいわけで、改めて接続をOpenする必要がないという理屈もナットクできます。

そういう解釈で、上記ソースを眺めていると、Loopの後、

cn.Close

に違和感を感じるわけです。OpenしていないのにCloseしている、という部分で「あれ?」と思って立ち止まったわけですが、Openしていない理由(=CuurentProjectの接続だから)を考えると、CurrentProjectなのに、cn.Closeしちゃっていいいのだろうか?──という疑問も沸いてくるわけです。

CurrentProjectなのだから、CloseせずにそのままSet cn = Nothingするものだと予測しながらソースを読んでいたのに、Closeする必要があるというのはどういうことなんだろう(SetでNothingすること自体には疑問は持っていません。Setはメモリアドレスの代入にすぎませんから、「オブジェクト変数cnに入ったメモリアドレスをNothingするんだろうなぁ」というくらいのものです)。

過去の自分のソースをみても、CurrentProject.Connectionでセットされたオブジェクト変数は皆ちゃんとCloseしているので、教本サンプルソースのミスというわけでもなさそうです(証拠のソース。ちなみにこれを書いていたときは踏襲元も思い出せないくらいのはるか過去からの踏襲/慣習で、なーんにも考えていなかったんです)。

ちなみにmdbが複数個存在していて、別のmdbからもうひとつのmdbの接続するときや、VB6.0からAccessへADO接続する際には、

Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Password='';User ID=admin;Data Source=" & MDB_PATH
cn.Open

で接続して(MDB_PATHは接続したいMDBのパスの入った変数だとします)

cn.Close
Set cn=Nothing

で終了するわけです。OpenとCloseをセットで使っていますし、この記述に対する疑問は特にはありません。

問題なのはCurrentProjectの接続です。Openせずに、Closeする。Openしない理由は予測できるとして、接続をCloseしてもCurrentProjectに影響しないAccessの接続って一体、どーなっているんだ?──と思って、今回改めてじっくりとヘルプを調べてみました。

すると、Connection プロパティのメモに

Connection プロパティは、実際にはアクティブなデータベースに対する ActiveX データ オブジェクト (ADO) 接続のコピーへの参照を返します。このため、Close メソッドを適用したり、Connection オブジェクトのメソッドやプロパティを使って接続を変更しようとしても、カレント データベースとの接続を保持する Access の実際の接続オブジェクトに影響を与えることはありません。

と書いているではありませんか。

接続のコピー!!

そうだったのかー。

CurrentProjectの一意の接続そのものではなく、その複製を受け渡していただけなんですね。しかもおそらく接続をOpenしたままでの複製です。だからOpenせずに、CloseしてもOKなんですね。「複製の受け渡しとは安全設計なんだなぁ、そもそもConnectionプロパティはReadOnlyだし、かなり用心部深いよね。でも考えてみればここまで用心するのも、道理といえば道理だな」──と一人でナットクしつつ、すっかり習慣化して、いまやとくに疑問にも思わずスルーしていた自分に打ちのめされました。足元のこと、わかってないわ…。

0 件のコメント: