見出し画像

JScriptでADOのレコードセットを切断する方法

レコードセットのActiveConnectionプロパティに、新しく作ったレコードセットのActiveConnectionを入れれば切断されます。

JScriptでは明示的にNothingを使えません。
ですが参照を切るためにはNothingが必要です。

実は新規作成したレコードセットのActiveConnectionプロパティの初期値はNothingです。
なので、それを利用させてもらうわけです。

nullの代入では切断できない

当初はnullの代入で切断されると思っていました。
ですが実際には切断されず、実行時エラーとなりました。

rst.ActiveConnection = null;

を実行したところ、実行時エラー

引数が間違った型、許容範囲外、または競合しています。

となりました。

VBScriptのNothingとJScriptのnullは同じようで違うものなのでしょう。

理解としては次のような感じでよいでしょうか。

・VBScriptのNothingは代入した瞬間に参照を切る。
・JScriptのnullは代入してもすぐには参照が切れない (参照を切るのはガベージコレクタのお仕事だから) 。

検証用コード

JScriptにVBScriptを共存させて、VBScriptでNothingかどうかを判断します。

レコードセットの切断は、コメントの「★★★レコードセットを切断する★★★」あたりでやっています。

<job id="TestDisconnectRecordSet">
<!-- VBScriptを使って、オブジェクトがNothingかどうかを調べる -->
<script language="VBScript">
 '''
 ''' オブジェクトがNothingかどうかを返します。
 '''
 Function ObjectIsNothing(piObj)
   ObjectIsNothing = piObj Is Nothing
 End Function
</script>
<!-- メイン処理はJScriptで実行する -->
<script language="JScript">
 var con = null;
 try
 {
   // DB接続
   con = new ActiveXObject("ADODB.Connection");
   // TODO: 接続文字列は環境に合わせて変える
   con.ConnectionString = "Provider=OraOLEDB.Oracle;User ID=scott;Password=tiger;Data Source=ORCL;";
   con.Open();
   
   // SQL実行
   var cmd = new ActiveXObject("ADODB.Command");
   cmd.CommandType = 1;  // adCmdText
   cmd.CommandText = "select sysdate from dual";
   cmd.ActiveConnection = con;
   
   var rst = new ActiveXObject("ADODB.RecordSet");
   rst.CursorLocation = 3; // adUseClient
   rst.Open(cmd);
   
   WScript.Echo("切断前:");
   WScript.Echo(rst(0).Value);
   
   // レコードセットの切断
   try
   {
     // 切断前の状態を表示する
     DispActiveConnectionRef(rst.ActiveConnection);
     
     // ★★★レコードセットを切断する★★★
     rst.ActiveConnection = (new ActiveXObject("ADODB.RecordSet")).ActiveConnection;
     
     // 切断できたかどうかを表示する
     WScript.Echo("");
     WScript.Echo("切断後:");
     DispActiveConnectionRef(rst.ActiveConnection);
   }
   catch (ex1)
   {
     WScript.Echo("Failed disconnect a recordset.\n" + ex1.message);
   }
   
   // 切断後も値が見られること
   WScript.Echo(rst(0).Value);
   
   // オブジェクト解放
   rst = null;
   cmd = null;
 }
 catch (ex)
 {
   WScript.Echo(ex.message);
 }
 finally
 {
   // DB切断
   if (con != null)
   {
     if (con.State != 0)
     {
       con.Close();
     }
     
     con = null;
   }
 }
 
 /**
  * ActiveConnectionがNothingかどうか表示します。
  */
 function DispActiveConnectionRef(con)
 {
   // VBScriptの関数で判定する
   if (ObjectIsNothing(con))
   {
     WScript.Echo("ActiveConnection is Nothing.");
   }
   else
   {
     WScript.Echo("ActiveConnection is not Nothing.");
   }
 }
</script>
</job>

上記のコードを「TestDisconnectRecordset.wsf」という名前で保存します。

それを実行した結果が次の内容です。

C:\WINDOWS\system32>CScript C:\tmp\TestDisconnectRecordset.wsf
切断前:
2021/03/21 23:39:24
ActiveConnection is not Nothing.

切断後:
ActiveConnection is Nothing.
2021/03/21 23:39:24

切断する前はNothingでありません。
これが切断後にはNothingになりました。
また、切断の前後でレコードセットの内容は変わりありません。

これなら問題ないでしょう。

補足 (JScript.NETの場合)

JScript.NETではこの方法でも切断できませんでした。

実行時エラー「呼び出しのターゲットが例外をスローしました。」が発生してしまいました。

黙ってADO.NET使えってことでしょうかね。

まとめ

JScriptでADOのレコードセットを切断したければ次のように書きましょう。

rst.ActiveConnection = (new ActiveXObject("ADODB.RecordSet")).ActiveConnection;

いいなと思ったら応援しよう!