[FIX] ADO でパラメータ化コマンドを使用すると接続がリークする

この記事は、以前は次の ID で公開されていました: JP247757
この資料は、アーカイブされました。これは "現状のまま" で提供され、更新されることはありません。
現象
Windows Foundation Classes for Java (WFC) と ADO を使用しているときに、パラメータ化コマンド オブジェクトを使用してレコードセットを開くと、適切に閉じられている接続が正しくプール、リサイクルされず、その結果接続がリークされます。この問題を回避するには、Java COM オブジェクトで ADO 接続を閉じた後に System.gc() を呼び出します。通常の状況では、ADO 接続を閉じた後にその接続を解放するために System.gc() を呼び出す必要はありません。
状況

Windows 2000

この問題を解決するためのモジュールは、Windows 2000 日本語版 Service Pack 2 以降に含まれています。
Windows 2000 日本語版の最新 Service Pack は、以下の Web サイトから入手できます。
詳細
この接続/セッション プーリングの問題は、以下の条件をすべて満たしているときに発生します。
  1. Microsoft Data Access Objects 2.1 SP2 がインストールされている。
  2. パラメータ化 ADO コマンド オブジェクトが使用された。
  3. Java COM オブジェクトが MTS または COM+ でホストされている。
  4. Java COM オブジェクトが切断されたレコードセットを作成する。

問題の再現手順

  1. Visual J++ 6.0 で、以下のコードを使用して、ConnLoss という名前の Java COM オブジェクトを作成します。
    import com.ms.wfc.data.*;public class ConnLoss{  // 次の接続文字列が実行中の SQL Server を指すように変更します。  private static String m_connect =     "Provider=SQLOLEDB;Server=(Local);Database=Pubs;UID=sa;PWD=;";  public com.ms.wfc.data.adodb._Recordset     FindAuthorsLastName( String au_id, boolean fCallGC )  {    Connection conn = null;    Command cmd   = null;    Recordset rs  = null;    try    {           // SQL Server への接続を開きます。      conn = new Connection();      conn.setCursorLocation( AdoEnums.CursorLocation.CLIENT );      conn.open( m_connect );            // コマンド オブジェクトを準備します。      cmd = new Command();      cmd.setActiveConnection( conn );            cmd.setCommandText( "select au_lname from authors where au_id=?" );          cmd.getParameters().append(         cmd.createParameter( "au_id",                    AdoEnums.DataType.VARCHAR,                   AdoEnums.ParameterDirection.INPUT,                   20, au_id ) );            // コマンドを実行します。      rs = cmd.execute();            // レコードセットを切断し、接続を閉じます。      rs.setActiveConnection( (Connection) null );      conn.close();            // 必要ならば、gc を呼び出します。      if (fCallGC) System.gc();            // 切断されたレコードセットを返します。      return (com.ms.wfc.data.adodb._Recordset) rs.getDataSource();          }    catch( AdoException adoEX )    {      // ここでエラーをログに記録します。    }    return null;  }}
  2. Java COM オブジェクトを MTS パッケージまたは COM+ パッケージに追加します。
  3. 次の Microsoft Visual Basic for Applications (VBA) コードを使用して、Java COM オブジェクトを呼び出します。
    Sub TestConnLoss()Dim objCL As ObjectDim i As LongDim rs As ADODB.recordset  set objCL = CreateObject("ConnLoss.ConnLoss")  For i = 1 To 100    Set rs = objCL.FindAuthorsLastName("756-30-7391", False)    Debug.Print rs.Fields("au_lname").Value    rs.Close    Set rs = Nothing      Next i    End Sub
  4. SQL Server 7.0 が存在するコンピュータで Windows NT パフォーマンス モニタを実行し、SQL Server:General Statistics パフォーマンス カウンタの User Connections を監視します。
  5. VBA クライアント コードを実行します。この時点で、Windows NT パフォーマンス モニタが報告しているように、このコードにより 100 個のユーザー接続が生成されます。このことは、Java COM オブジェクトが使用する SQL OLE DB プロバイダに対して OLE DB セッション プーリングが正しく機能していないことを示しています。

  6. System.gc() コードをアクティブにするには、FindAuthorsLastName の 2 番目のパラメータを True に変更します。
  7. MTS パッケージまたは COM+ パッケージを停止し、再開します。
  8. 再度 VBA クライアント コードを実行します。
この時点では、コードにより生成されるユーザー接続はわずかで、System.gc() が呼び出されるときに、Java COM オブジェクトが使用する SQL OLE DB プロバイダに対して OLE DB セッション プーリングが正しく機能していることを示しています。

: System.gc() を呼び出すと、Java COM オブジェクトのパフォーマンスに大きな影響を与えます。したがって、一般的にパフォーマンスの面からは、System.gc() の呼び出しを避ける必要があります。たとえば、メソッドごとに System.gc() を呼び出すことによるパフォーマンスへの影響を軽減するために、10 または 100 個のメソッド呼び出しごとに一度だけ System.gc() を呼び出すビジネス オブジェクトを作成できます。または、ハード コードされたパラメータ値を SQL 文字列に渡し、上記の例のようにパラメータ トークンを使用しないで、パラメータ化コマンド オブジェクトの使用を避けます。これによっても同様に問題を回避できます。
関連情報
この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 247757 (最終更新日 2001-02-28) をもとに作成したものです。

警告: この記事は自動翻訳されています

プロパティ

文書番号:247757 - 最終更新日: 02/23/2014 11:19:33 - リビジョン: 4.0

Microsoft Data Access Components 2.1 Service Pack 2, Microsoft Data Access Components 2.5, Microsoft Visual J++ 6.0 Standard Edition

  • kbnosurvey kbarchive kbbug kbfix kbqfe kbmdac250bug kbmts kbgrpdsjava kbado210sp2bug kbhotfixserver KB247757
フィードバック
ERROR: at System.Diagnostics.Process.Kill() at Microsoft.Support.SEOInfrastructureService.PhantomJS.PhantomJSRunner.WaitForExit(Process process, Int32 waitTime, StringBuilder dataBuilder, Boolean isTotalProcessTimeout)