トップ回答者
ADODBの使用について

質問
-
既存のプロジェクトがVB.NETなのにSystem.Data.SqlClient.SqlConnectionが使用されていません。
つまりADO.NETではありません。
環境
VS2003 VB.NET Framework1.1
http://support.microsoft.com/kb/318559/ja
1. Visual Studio .NET プロジェクトを開きます。 2. [プロジェクト] メニューの [参照の追加] をクリックします。 3. [参照の追加] ダイアログ ボックスで、[.NET] タブをクリックします。 4. [コンポーネント名] ボックスの一覧の [adodb] をクリックして [選択] をクリックし、[OK] をクリックします。 の方法で使用されています。
ADO PIA で動作しています。(と思っています)
OLE接続(接続文字列にProvider=SQLOLEDB.1が書かれています )
4.2 ADO.NETによるADOレコードセットの読み込みhttp://www.atmarkit.co.jp/fdotnet/special/vb6tovb2005mig03/vb6tovb2005mig03_01.html
※この例は(PIA)でなく(IA)です。
この例と同じ様に
ADODB.Connection
ADODB.Recordset
ADODB.Command
を使用しています。Q1
Marshal.ReleaseComObject対象は下記の3つでよいか教えてください。
ADODB.Connection
ADODB.Recordset
ADODB.Command(PIA なのでFields 、 Fieldはがマネージオブジェクトであると思っています)
Q2
既存のプロジェクトでは3つに対してMarshal.ReleaseComObject
は行われていません。この場合、GC任せになっているのか、残り続けるのかどちらの状態になっているのか教えてください。
回答
-
自己レス
ADODB.Connection
ADODB.Recordset
ADODB.Command
ADODB.FieldsADODB.Field
System.Runtime.InteropServices.Marshal.IsComObjectで調べた所
True
True
True
False
False
でした
ADODB.Fields
ADODB.Field
に関しては
ReleaseComObjectで例外があがります。
なので上記レスの
-----------------------------------------------------------
OK例
dim fields as ADODB.Fields = recordset.Fields
dim field as ADODB.Field = fields.Item("hogeName")
dim hogeName as string = Convert.ToString(field.value)
Marshal.ReleaseComObject(field)
Marshal.ReleaseComObject(fields)Marshal.ReleaseComObject(recordset)
という事でしょうか?
その通りです。
-----------------------------------------------------------
の箇所は誤りです。
ADODB.Connection
ADODB.Recordset
ADODB.Command
の3つをMarshal.ReleaseComObjectする必要があります。
すべての返信
-
いくみ さんからの引用 Q1
Marshal.ReleaseComObject対象は下記の3つでよいか教えてください。
ADODB.Connection
ADODB.Recordset
ADODB.Command(PIA なのでFields 、 Fieldはがマネージオブジェクトであると思っています)
ADOのオブジェクトはすべてマネージオブジェクトにはならないと思います。
よって、FieldsなどもすべてReleaseComObject対象です。
いくみ さんからの引用 Q2
既存のプロジェクトでは3つに対してMarshal.ReleaseComObject
は行われていません。この場合、GC任せになっているのか、残り続けるのかどちらの状態になっているのか教えてください。
アンマネージなものはGC任せにはなりません。
-
レスありがとうございます。
Q1
>よって、FieldsなどもすべてReleaseComObject対象です。
Exlec comの感覚で書きますと
使用方法としては
NG例 fields,fieldが開放されない。
dim hogeName as string = Convert.ToString(recordset.Fields.Item("hogeName").Value)
Marshal.ReleaseComObject(recordset)
OK例dim fields as ADODB.Fields = recordset.Fields
dim field as ADODB.Field = fields.Item("hogeName")
dim hogeName as string = Convert.ToString(field.value)
Marshal.ReleaseComObject(field)
Marshal.ReleaseComObject(fields)Marshal.ReleaseComObject(recordset)
という事でしょうか?
Q2
>アンマネージなものはGC任せにはなりません。
既存のコードは使用する度にメモリリークしているということですね?
-
いくみ さんからの引用 OK例
dim fields as ADODB.Fields = recordset.Fields
dim field as ADODB.Field = fields.Item("hogeName")
dim hogeName as string = Convert.ToString(field.value)
Marshal.ReleaseComObject(field)
Marshal.ReleaseComObject(fields)Marshal.ReleaseComObject(recordset)
という事でしょうか?
その通りです。
いくみ さんからの引用 Q2
>アンマネージなものはGC任せにはなりません。
既存のコードは使用する度にメモリリークしているということですね?
メモリリークという状態になっているかどうかは不明(管理対象外)です。
でも、メモリリークしている前提でいた方が良いかと。
-
早々のレスありがとうございます。
現在の私の関わっているプロジェクトはPIAで作られています。
[参照の追加] -[.NET]
C:\Program Files\Microsoft.NET\Primary Interop Assemblies\ADODB.dll
(PIA)
[参照の追加] -[.COM]
C:\TestProject\obj\Interop.ADODB.dll
(IA)
http://bbs.wankuma.com/index.cgi?mode=al2&namber=7478&KLOG=19
>一方、PIA の場合は、Fields や Field がマネージオブジェクトになっているため、
>これらのオブジェクトについては、ReleaseComObject メソッドの呼び出しが不要です。http://hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?no=7177&reno=7174&oya=7168&mode=msgview&page=0
>なお、ADODB.DLL の方は、Fields コレクションや Parameters コレクションなどが
>マネージオブジェクトになっていますがhttp://hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?mode=allread&no=6850&page=120
>PIA (Adodb.dll)の場合、Fileds コレクション等は COM オブジェクトではありませんが、
>IA (msado15.dll 等)の場合は COM なので、ReleaseComObject が必要です。Q3 上記の掲示板のコメントからすると
ADODB.Connection
ADODB.Recordset
ADODB.CommandはMarshal.ReleaseComObjectが必要ですが
Fields,Fieldは不要の様に書かれています。
PIAの場合のADODBでアンマネージとマネージオブジェクトを区別する方法
または、それらに関する記述をMSDNからそれらの情報を探してるのですが、みつかってないです。
情報お持ちの方 いらっしゃいましたら教えてください。
------------------------------------------------------------------------------------------
ADO プライマリ相互運用アセンブリ (primary interop assembly) を使用する。
http://support.microsoft.com/kb/321415/ja
ADO が正常に動作するためには、使用するクラスのクラス名の最後に、
必ず "Class" という単語が含まれている必要があります。次に例を示します。
ADODB.ConnectionClass
ADODB.RecordsetClass
ADODB.CommandClassこれらのオブジェクトを使用する場合は、この資料で説明した ReleaseComObject を使用して
COM で参照が解放されるようにします。
------------------------------------------------------------------------------------------そもそも
ADODB.Connection
ADODB.Recordset
ADODB.Commandを使用している時点で間違っているのではないかという気がしますが・・・。
既存のプロジェクトは動作しています。
-
自己レス
ADODB.Connection
ADODB.Recordset
ADODB.Command
ADODB.FieldsADODB.Field
System.Runtime.InteropServices.Marshal.IsComObjectで調べた所
True
True
True
False
False
でした
ADODB.Fields
ADODB.Field
に関しては
ReleaseComObjectで例外があがります。
なので上記レスの
-----------------------------------------------------------
OK例
dim fields as ADODB.Fields = recordset.Fields
dim field as ADODB.Field = fields.Item("hogeName")
dim hogeName as string = Convert.ToString(field.value)
Marshal.ReleaseComObject(field)
Marshal.ReleaseComObject(fields)Marshal.ReleaseComObject(recordset)
という事でしょうか?
その通りです。
-----------------------------------------------------------
の箇所は誤りです。
ADODB.Connection
ADODB.Recordset
ADODB.Command
の3つをMarshal.ReleaseComObjectする必要があります。