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;