PowerShell から ODP.NET managed driver を使って Oracle 接続する

2021年11月23日

Windows のシステム管理者なんてやってると、ちょっとした監視ツールを作ったりする機会がありますが、PowerShell から Oracle 接続してSQLなんて投げられると大変便利です。今回は ODP.NET managed driver を使って Oracle に対して SELECT 文を投げてみます。

ODP.NET のダウンロード

ネットを漁ってると、PowerShell からの Oracle へのアクセスは、ADO.NET(System.Data.OracleClient)のサンプルが多いですが、なんでも .NET 4.0 以降は非推奨となったようです。なので、Oracle Data Provider for .NETを利用します。ODP.NET は Oracle Data Access Components (ODAC) の一部で「64-bit Oracle Data Access Components (ODAC) ダウンロード」より取得します。

ODP.NET のダウンロード

ダウンロード後は任意の場所に展開しておけば良いです。特にインストール等は不要です。

ここで注意ですが、"ODP.NET_Managed_ODAC12cR4.zip” は Oracle.DataAccess ではなく、Oracle.ManagedDataAccess です。ODP.NET managed driver というそうです。

何が違うのかは「ODP.NETドライバの相違点」に記載があります。ちなみに ODP.NET unmanaged driver は、"ODAC121024Xcopy_x64.zip" に入ってます。

マニュアルには managed = 管理対象 と記載されていますが、これ .NET 用語の「マネージドコード」のことだと思うので、何となく誤訳が感満載な気がします。

CAS ポリシーが規定で有効になっていない?

ダウンロードしてきた ODP.NET managed driver を PowerShell からアセンブリロードしようとすると、以下のエラーに出くわします。

ネットワーク上の場所からアセンブリを読み込もうとしました。これにより、以前のバージョンの .NET Framework で、アセンブリがサンドボックス化された可能性があります。このリリースの .NET Framework では、CAS ポリシーが既定で有効になっていないため、この読み込みは危険な場合があります。この読み込みがアセンブリのサンドボックス化を目的としない場合は、loadFromRemoteSources スイッチを有効にしてください。詳細については
、http://go.microsoft.com/fwlink/?LinkId=155569 を参照してください。

CAS というのは、コードアクセスセキュリティのことで簡単に言うとダウンロードしてきたものを簡単には実行させないよ、というもののようです。該当するファイルのプロパティで「ブロックの解除」にチェックを入れれば大丈夫です。

CAS ポリシーの解除

SQL 文の実行

これもネットにたくさんサンプルあるので説明はばっさり省きますが、先頭でアセンブリをロードするところだけ注意すれば特に問題なく接続できると思います。ネットにあまりサンプルがなかったバインド変数付きで記載しておきます。

エラー処理はまじめにやってませんが、そのあたりは適当に対処してください。

# ODP.NETをロード
[void][Reflection.Assembly]::LoadFile("C:\ODP.NET_Managed_ODAC12cR4\odp.net\managed\common\Oracle.ManagedDataAccess.dll")

# 接続文字列
$constring="User Id=scott;Password=tiger;Data Source=localhost:1521/ORCL"

# SQL定義
$sql = "select col1,col2,col3 from sample1 where col2 like :col2"

# 接続
$con = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($constring)
$con.Open()

# SQL実行
$cmd = New-Object Oracle.ManagedDataAccess.Client.OracleCommand($sql,$con)
[void]$cmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter "col2", "TEST%"))
$reader = $cmd.ExecuteReader()
while( $reader.Read() )
{
    $col1 = $reader.GetInt32(0)
    $col2 = $reader.GetString(1)
    $col3 = $reader.GetString(2)

    "## COL1=[{0}],COL2=[{1}],COL3=[{2}]" -f $col1,$col2,$col3
}
# 切断
$reader.Dispose()
$con.Close()

ちなみに OracleParameter を使ってバインド変数に値を設定している箇所($cmd.Parameters.Add)ですが、データの型まできちんと指定する場合は以下のように書きます。詳細は OracleParameter クラス を参照ください。

[void]$cmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter "col2",([Oracle.ManagedDataAccess.Client.OracleDbType]::Varchar2), "TEST%",([System.Data.ParameterDirection]::Input)))

WindowsPowerShell

Posted by takmaru