ODP.NET (Oracle Data Provider for .NET)

Visual Basic(VB6.0A)からOracleへアクセスする方法として oo4o を使った内容を以前から載せてはいましたが、 時代はVB.NETでの開発となり、ADO.NET の方式が主流となってきました。 ADO.NET とは、SQL Server や XML などのデータソースや、OLE DBやODBC経由でデータ ソースに対する一貫性を持ったアクセスができる仕組みです。

オラクルも「.NET」に対応するために、ネイティブにデータベースにアクセスできる「Oracle Data Provider for .NET」(ODP.NETと略します)を提供しています。 基本的な関数などはADO.NETと似た部分が多いですが、オラクル独自の機能が使用可能です。


ODP.NET使用の準備

ODP.NETを使用するためには、Oracle Clientをインストールするのがいいのですが、 .NETからデータベースへのアクセスのみを行いたい場合はOracle Data Access Components のインストールで十分です。

オラクルの 「Oracle Data Access Components (ODAC) for Windows ダウンロード」 ページから該当するダウンロードを選びます。

私は32ビット用の 「32-bit ODAC with ODT ダウンロード」 を選びました。 このページを見ますと多くのバージョンがダウンロードできますが、私はオラクルサーバのバージョンに合わせて ODAC 11.2 Release 5 and Oracle Developer Tools for Visual Studio (11.2.0.3.20)をダウンロードしました。

■「ODTwithODAC1120320_32bit.zip」をダウンロードし、デスクトップZIPファイルを解凍します。


■「setup.exe」を実行し、順次画面に従い必要な項目を入力しながら進めます。
 ほぼ以下の画像の設定の様に進めればインストールが終了します。(画面は左から右へ、上から下に進みます)


■インストール後「C:\oracle」フォルダに登録されていることを確認します。
 オラクルへのアクセスに必要なものは「C:\oracle\odp.net\bin\2.x\Oracle.DataAccess.dll」です。  (.NET4の場合には「C:\oracle\odp.net\bin\4\Oracle.DataAccess.dll」です。)


■VisualStudioでの参照設定
 ソリューションエクスプローラの中の参照設定で、「参照の追加」を行います。  参照の追加のダイアログで、「参照」タブの中から、「C:\oracle\odp.net\bin\2.x\Oracle.DataAccess.dll」を設定します。


これで、VB.NET から ODP.NET を利用する準備ができました。


Oracleへの接続と切断

Orcaleへの接続と切断のみの処理を、フォームに貼り付けたコマンドボタンのクリックイベントでテストします。 ODP.NETを使うためには「Oracle.DataAccess.Client」をソースの先頭で宣言したほうが良いでしょう。

接続のために、Orcaleの接続用オブジェクトの OracleConnection を使用します。 OracleConnection に接続文字列を渡して、オブジェクトの生成を行っています。

■簡易接続ネーミング・メソッドを使用した接続文字列について

//<ホスト名>[:<ポート番号>][/<データベース名(SID)>]

  (ポート番号省略時は”:1521”が指定されたものとする)
Instant Clientのtnsnames設定(tnsnames.oraファイル)を構成することなく、アプリケーションから直接データベースに対する接続文字列を指定できます。 ソース内でコメントの接続文字列は、プログラムをサーバ上で動作させる場合で、localhost の設定でOKです。

01'ソースの先頭で以下のImportを宣言
02Imports Oracle.DataAccess.Client
03'-----
04 
05'オラクル接続のオープン・クローズのテスト
06Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
07    '接続文字列
08    Dim strConnect As String = _
09        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
10    'Dim strConnect As String = _
11    '   "Data Source=//localhost/test; User ID=test;Password=test;"
12    'オラクル接続オブジェクト
13    Dim Conn As New OracleConnection(strConnect)
14    'オラクル接続オープン
15    Conn.Open()
16    'オラクル接続クローズ
17    Conn.Close()
18    Conn.Dispose()
19End Sub

オラクル接続オブジェクト OracleConnection のメソッド Open・Close を使用して接続のオープン・クローズを行います。

簡単な接続はこれでいいのですが、実際にはエラー処理が必要になります。
VB.NET ではエラー処理に Try...Catch...End Try ブロック構造を使用します。
ODP.NETにはエラーが発生したときに Catch でスローされる OracleExceptionクラスがありますので、これを使った例を以下に示します。

01'オラクル接続のオープン・クローズのテスト2
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列(エラーが発生するようにPasswordは"test2"としている)
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test2;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'オラクル接続クローズ
12        Conn.Close()
13    Catch exora As OracleException
14        'オラクルエラー
15        MsgBox(exora.Number & ":" & exora.Message)
16    Catch ex As Exception
17        'PGエラー
18        MsgBox(ex.Message)
19    Finally
20        Conn.Dispose()
21    End Try
22End Sub

上記の例では、エラーを起こすためにパスワードを間違ったものにしています。 このプログラムを実行すると、以下のメッセージが表示されます。


SQLの実行その1:簡単なSELECT文の実行

データベース内のデータを検索するSQL文としてのSELECT文の実行を行います。
ここでは簡単なSELECT文として、DUAL擬似表からシステム日付を取得する処理を示します。

ODP.NET では以下のオブジェクトを使用しテーブルからのデータを取得します。

オブジェクト名 概要 備考
OracleConnection データベースへの接続オブジェクト データベース接続文字列を渡して接続処理を行う
OracleCommand データベースに対して実行する SQL ステートメントまたは
ストアド プロシージャ用オブジェクト
SQL文と接続オブジェクト渡して SQL文(ストアド・プロシージャまたはテーブル名)と接続オブジェクト渡して、OracleCommandオブジェクトにリクエストをカプセル化します。OracleCommandオブジェクトは、リクエストを作成してデータベースに送信し、結果を戻します。
OracleDataReader データ行の前方向ストリームを読み取るオブジェクト OracleCommandオブジェクトのExecuteReader()メソッドによりOracleDataReaderオブジェクトが返されます。

■処理手順
・接続文字列の生成
・オラクル接続オブジェクトの生成
・オラクル接続オープン
・コマンドオブジェクトの生成
・コマンドオブジェクトの実行で読込オブジェクト取得
・データ行の読込処理
・読込が正常の場合、各データの取得
・読込オブジェクトのクローズ
・オラクル接続クローズ

01'簡単なSELECT文の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'SQL文
12        Dim SQL As String = _
13        "SELECT SYSDATE, TO_CHAR(SYSDATE, 'YYYY/MM/DD') AS DATEX FROM DUAL"
14        'コマンドオブジェクト(SQL文と接続オブジェクト)
15        Dim Cmd As New OracleCommand(SQL, Conn)
16        Cmd.CommandType = CommandType.Text
17        'コマンドオブジェクトの実行で読込オブジェクト取得
18        Dim dr As OracleDataReader = Cmd.ExecuteReader()
19        'データ行の読込処理
20        If dr.Read() = True Then
21            '読込が正常の場合、各データの取得
22            MsgBox(dr.Item("SYSDATE") & ":" & dr.Item("DATEX")) '取得①
23            MsgBox(dr.Item(0) & ":" & dr.Item(1))               '取得②
24            MsgBox(dr(0) & ":" & dr("DATEX"))                   '取得③
25            MsgBox(dr.GetDateTime(0) & ":" & dr.GetString(1))   '取得④
26        End If
27        '読込オブジェクトのクローズ
28        dr.Close()
29        dr = Nothing
30        'オラクル接続クローズ
31        Conn.Close()
32    Catch exora As OracleException
33        'オラクルエラー
34        MsgBox(exora.Number & ":" & exora.Message)
35    Catch ex As Exception
36        'PGエラー
37        MsgBox(ex.Message)
38    Finally
39        Conn.Dispose()
40    End Try
41End Sub
■注意点

データ行の読込が正常でのデータの取得の所で、4種類の方法を示しています。
取得①
 OracleDataReaderオブジェクトのプロパティ Item にカラム名文字列を与えて、カラムの値を取得しています。
取得②
 OracleDataReaderオブジェクトのプロパティ Item にカラムIndexを与えて、カラムの値を取得しています。
 この場合は、Indexとしては 0 , 1 しか設定できません。
取得③
 OracleDataReaderオブジェクトのプロパティ Item はデフォルト・プロパティなので、(C#ではインデクサというらしい) OracleDataReaderに直接カラム名文字列を与えることで、カラムの値を取得できます。
取得④
 OracleDataReader型指定アクセッサを使用してデータ取得を行います。
 型指定アクセッサは、Oracleネイティブ・データ型.NETタイプに変換するメソッドです。
 厳密にデータ変換を行いたいのであれば、この方法がベストだと思います。

■代表的な型指定アクセッサについて

Oracleネイティブ・データ型 .NETタイプ 型指定アクセッサ
BLOB System.Byte() GetBytes
CHAR System.String
System.Char()
GetString
GetChars
DATE System.DateTime GetDateTime
NUMBER System.Decimal
System.Byte
System.Int16
System.Int32
System.Int64
System.Single
System.Double
GetDecimal
GetByte
GetInt16
GetInt32
GetInt64
GetFloat
GetDouble
NCHAR System.String
System.Char()
GetString
GetChars
VARCHAR2 System.String
System.Char()
GetString
GetChars
NVARCHAR2 System.String
System.Char()
GetString
GetChars

■関連記事
Oracle SQL SELECT1 : SELECT文の基礎

SQLの実行その2:複数行を返すSELECT文の実行

SQLの実行その1のSELECT文では1行しか結果を返さないことがはっきりしていましたが、 複数行を返すSELECT文を実行することのほうが実際には多いものです。

以下のプログラムでは、TM_商品の商品コードと商品名の一覧を表示する処理を行っています。
「SQLの実行その1」との違いは、読込処理で OracleDataReader.read() の結果が True ではなくなるまで Whileループ で処理をしているところです。 OracleDataReader.read() は読込む行が無くなると False を返します。

01'複数行を返すSELECT文の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'SQL文
12        Dim SQL As String = "SELECT 商品コード, 商品名 FROM TM_商品"
13        'コマンドオブジェクト(SQL文と接続オブジェクト)
14        Dim Cmd As New OracleCommand(SQL, Conn)
15        Cmd.CommandType = CommandType.Text
16        '読込オブジェクトに接続
17        Dim dr As OracleDataReader = Cmd.ExecuteReader()
18        Dim strDsp As String = ""
19        '読込処理
20        While (dr.Read() = True)
21            '読込行が在った場合
22            strDsp &= dr.Item("商品コード").ToString & ":" & dr.Item("商品名") & vbCr
23        End While
24        '読込データの表示
25        MsgBox(strDsp)
26        '読込オブジェクトのクローズ
27        dr.Close()
28        dr = Nothing
29        'オラクル接続クローズ
30        Conn.Close()
31    Catch exora As OracleException
32        'オラクルエラー
33        MsgBox(exora.Number & ":" & exora.Message)
34    Catch ex As Exception
35        'PGエラー
36        MsgBox(ex.Message)
37    Finally
38        Conn.Dispose()
39    End Try
40End Sub

SQLの実行その3:INSERT,UPDATE,DELETE文の実行

SELECT文以外のDML(データ操作言語)であるINSERT,UPDATE,DELETE文の実行を OracleCommandオブジェクトのメソッドである ExecuteNonQuery を用いて行います。 ExecuteNonQuery の戻り値は処理された行数が返されます。

■1個のINSERT文の実行
01'1個のINSERT文の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'SQL文
12        Dim SQL As String = _
13          "INSERT INTO TM_商品(商品コード, 商品名, 商品区分, 仕入単価, 売上単価)" & _
14          " VALUES(1001,'商品1001', '区分1001', 10000, 15000)"
15        'コマンドオブジェクト(SQL文と接続オブジェクト)
16        Dim Cmd As New OracleCommand(SQL, Conn)
17        'INSERT文の実行
18        Dim nCnt As Integer = Cmd.ExecuteNonQuery()
19        'オラクル接続クローズ
20        Conn.Close()
21    Catch exora As OracleException
22        'オラクルエラー
23        MsgBox(exora.Number & ":" & exora.Message)
24    Catch ex As Exception
25        'PGエラー
26        MsgBox(ex.Message)
27    Finally
28        Conn.Dispose()
29    End Try
30End Sub

以下は連続で、INSERT、UPDATE、DELETE文の実行を行います。
上の「1個のINSERT文の実行」でも、以下の例でも、DML文の実行は成功した場合にその都度コミットされています。

■INSERT,UPDATE,DELETE文の実行
01'INSERT,UPDATE,DELETE文の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'INSERT-SQL文1
12        Dim SQL As String = _
13          "INSERT INTO TM_商品(商品コード, 商品名, 商品区分, 仕入単価, 売上単価)" & _
14          " VALUES(1001,'商品1001', '区分1001', 10000, 15000)"
15        'コマンドオブジェクト(SQL文と接続オブジェクト)
16        Dim Cmd As New OracleCommand(SQL, Conn)
17        'INSERT文の実行
18        Dim nCnt As Integer = Cmd.ExecuteNonQuery()
19 
20        'INSERT-SQL文2
21        SQL = "INSERT INTO TM_商品(商品コード, 商品名, 商品区分, 仕入単価, 売上単価)" & _
22              " VALUES(1002,'商品1002', '区分1002', 10000, 15000)"
23        'コマンドオブジェクトへのSQL文設定
24        Cmd.CommandText = SQL
25        'INSERT文の実行
26        nCnt = Cmd.ExecuteNonQuery()
27 
28        'UPDATE-SQL文
29        SQL = "UPDATE TM_商品 SET 売上単価 = 20000 WHERE 商品コード = 1001"
30        'コマンドオブジェクトへのSQL文設定
31        Cmd.CommandText = SQL
32        'UPDATE文の実行
33        nCnt = Cmd.ExecuteNonQuery()
34 
35        'DELETE-SQL文
36        SQL = "DELETE TM_商品 WHERE 商品コード = 1002"
37        'コマンドオブジェクトへのSQL文設定
38        Cmd.CommandText = SQL
39        'DELETE文の実行
40        nCnt = Cmd.ExecuteNonQuery()
41 
42        'オラクル接続クローズ
43        Conn.Close()
44     Catch exora As OracleException
45        'オラクルエラー
46        MsgBox(exora.Number & ":" & exora.Message)
47    Catch ex As Exception
48        'PGエラー
49        MsgBox(ex.Message)
50    Finally
51        Conn.Dispose()
52    End Try
53End Sub
■関連記事
Oracle SQL・データの追加(INSERT)
Oracle SQL・データの更新(UPDATE)
Oracle SQL・データの削除(DELETE)

SQLの実行その4:トランザクションを加味したINSERT,UPDATE,DELETE文の実行

「SQLの実行その3:INSERT,UPDATE,DELETE文の実行」ではDML文の実行の都度コミットがされてしまうので、 途中でエラーが在った場合はそこまでの結果がデータに残ってしまいます。
そこで、トランザクション処理をDML文の実行の前後で掛けてやれば、エラーが在った場合には更新処理が反映されません。

以下の例では、OracleConnectionオブジェクトのBeginTransactionメソッドを用いて、 トランザクション開始しOracleTransactionオブジェクトを取得します。
OracleCommandオブジェクトにOracleTransactionオブジェクトを関連付けた後で、DML文の実行を行います。
各DML文の実行が正常に終わった後に、OracleTransactionオブジェクトのCommitを行って、全てのDML文の確定を行います。 尚、オラクルエラーやプログラムエラーが在った場合には、OracleTransactionオブジェクトのRollbackを行って、 全てのDML文の結果の反映を廃棄を行います。

01'トランザクションを加味したINSERT,UPDATE,DELETE文の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05        "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    'トランザクションオブジェクト
09    Dim Trans As OracleTransaction = Nothing
10    Try
11        'オラクル接続オープン
12        Conn.Open()
13        'トランザクション開始
14        Trans = Conn.BeginTransaction(IsolationLevel.ReadCommitted)
15 
16        'INSERT-SQL文1
17        Dim SQL As String = _
18          "INSERT INTO TM_商品(商品コード, 商品名, 商品区分, 仕入単価, 売上単価)" & _
19          " VALUES(1001,'商品1001', '区分1001', 10000, 15000)"
20        'コマンドオブジェクト(SQL文と接続オブジェクト)
21        Dim Cmd As New OracleCommand(SQL, Conn)
22        'トランザクションをコマンドオブジェクトに関連付け
23        Cmd.Transaction = Trans
24        'INSERT文の実行
25        Dim nCnt As Integer = Cmd.ExecuteNonQuery()
26 
27        'INSERT-SQL文2
28        SQL = "INSERT INTO TM_商品(商品コード, 商品名, 商品区分, 仕入単価, 売上単価)" & _
29              " VALUES(1002,'商品1002', '区分1002', 10000, 15000)"
30        'コマンドオブジェクトへのSQL文設定
31        Cmd.CommandText = SQL
32        'INSERT文の実行
33        nCnt = Cmd.ExecuteNonQuery()
34 
35        'UPDATE-SQL文
36        SQL = "UPDATE TM_商品 SET 売上単価 = 20000 WHERE 商品コード = 1001"
37        'コマンドオブジェクトへのSQL文設定
38        Cmd.CommandText = SQL
39        'UPDATE文の実行
40        nCnt = Cmd.ExecuteNonQuery()
41 
42        'DELETE-SQL文
43        SQL = "DELETE TM_商品 WHERE 商品コード = 1002"
44        'コマンドオブジェクトへのSQL文設定
45        Cmd.CommandText = SQL
46        'DELETE文の実行
47        nCnt = Cmd.ExecuteNonQuery()
48 
49        'コミット実行
50        Trans.Commit()
51        'オラクル接続クローズ
52        Conn.Close()
53    Catch exora As OracleException
54        'ロールバック実行
55        Trans.Rollback()
56        'オラクルエラー
57        MsgBox(exora.Number & ":" & exora.Message)
58    Catch ex As Exception
59        'ロールバック実行
60        Trans.Rollback()
61        'PGエラー
62        MsgBox(ex.Message)
63    Finally
64        Conn.Dispose()
65    End Try
66End Sub
■関連記事
トランザクション・ロック

BLOB型の利用方法:画像データをテーブルに設定


■テーブルにBLOB型を設定しその中に画像データファイルを格納する方法を以下に示します。

テストを行うためのBLOBフィールドを持つテーブルを用意します。(以下のCREATE文でテーブルを作成)

1CREATE TABLE TT_BLOB(
2    ID    NUMBER(5,0) primary key,
3    BLOB  blob
4);

画像ファイルはテストのため、「test.png」というファイル名とします。(画像の内容は「Oracleへの接続と切断」でメッセージとして表示しているものです)
このファイルを全てバイト配列に読込み、その値を全てBLOBフィールドに登録します。
INSERT文の定義の文字列の中で「:blob」がありますが、コマンドオブジェクトを生成した後でこの引数名で値を設定できます。 というよりもBLOB型のフィールドにはSQL文で直接記述できないためこの方法を用います。

01'BLOBデータの新規追加の実行
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05    "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'テスト画像データをバイト配列に読込
07    Dim fs As New System.IO.FileStream("test.png", IO.FileMode.Open, IO.FileAccess.Read)
08    Dim blob(fs.Length) As Byte
09    fs.Read(blob, 0, fs.Length)
10    'オラクル接続オブジェクト
11    Dim Conn As New OracleConnection(strConnect)
12    Try
13        'オラクル接続オープン
14        Conn.Open()
15        'INSERT-SQL文
16        Dim SQL As String = "INSERT INTO TT_BLOB(ID, BLOB) VALUES(1, :blob)"
17        'コマンドオブジェクト(SQL文と接続オブジェクト)
18        Dim Cmd As New OracleCommand(SQL, Conn)
19        '引数の定義
20        Dim prm As OracleParameter = Cmd.Parameters.Add("blob", OracleDbType.Blob)
21        'BLOBデータの設定
22        prm.Value = blob
23        'INSERT文の実行
24        Dim nCnt As Integer = Cmd.ExecuteNonQuery()
25        'オラクル接続クローズ
26        Conn.Close()
27    Catch exora As OracleException
28        'オラクルエラー
29        MsgBox(exora.Number & ":" & exora.Message)
30    Catch ex As Exception
31        'PGエラー
32        MsgBox(ex.Message)
33    Finally
34        Conn.Dispose()
35    End Try
36End Sub


楽天市場

■BLOBデータを取得し表示

上で登録されたBLOBデータを読込んで、フォーム上のPictureBoxに設定し表示します。

SELECT文でBLOBデータのカラムを指定し、コマンドオブジェクトを生成後、OracleDataReaderで読み込み処理を行います。 OracleDataReaderGetOracleBlob メソッドでBLOBデータの取得を行い、MemoryStreamオブジェクトに変換後、 PictureBoxに画像設定を行います。

01'BLOBデータの表示
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05    "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'オラクル接続オブジェクト
07    Dim Conn As New OracleConnection(strConnect)
08    Try
09        'オラクル接続オープン
10        Conn.Open()
11        'SELECT-SQL文
12        Dim SQL As String = "SELECT BLOB FROM TT_BLOB WHERE ID = 1"
13        'コマンドオブジェクト(SQL文と接続オブジェクト)
14        Dim Cmd As New OracleCommand(SQL, Conn)
15        Cmd.CommandType = CommandType.Text
16        '読込オブジェクトに接続
17        Dim dr As OracleDataReader = Cmd.ExecuteReader()
18        '読込処理
19        If dr.Read Then
20            'BLOBデータの取得
21            Dim blob As Oracle.DataAccess.Types.OracleBlob = dr.GetOracleBlob(0)
22            'BLOBデータをMemoryStreamオブジェクトに変換
23            Dim mstr As New System.IO.MemoryStream(blob.Value)
24            '画像設定
25            PictureBox1.Image = New Bitmap(mstr)
26        End If
27        '読込オブジェクトのクローズ
28        dr.Close()
29        dr = Nothing
30        'オラクル接続クローズ
31        Conn.Close()
32    Catch exora As OracleException
33        'オラクルエラー
34        MsgBox(exora.Number & ":" & exora.Message)
35    Catch ex As Exception
36        'PGエラー
37        MsgBox(ex.Message)
38    Finally
39        Conn.Dispose()
40    End Try
41End Sub

■BLOBデータ更新1:OracleCommandおよびOracleParameterを使用したLOBの更新

既に存在するBLOBデータを更新する方法は、新規追加の場合と同じになります。違いはSQL文がUPDATE文である点のみです。

01'BLOBデータの更新の実行1
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05    "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'テスト画像データをバイト配列に読込
07    Dim fs As New System.IO.FileStream("test2.png", IO.FileMode.Open, IO.FileAccess.Read)
08    Dim blob(fs.Length) As Byte
09    fs.Read(blob, 0, fs.Length)
10    'オラクル接続オブジェクト
11    Dim Conn As New OracleConnection(strConnect)
12    Try
13        'オラクル接続オープン
14        Conn.Open()
15        'UPDATE-SQL文
16        Dim SQL As String = "UPDATE TT_BLOB SET BLOB = :blob WHERE ID = 1"
17        'コマンドオブジェクト(SQL文と接続オブジェクト)
18        Dim Cmd As New OracleCommand(SQL, Conn)
19        '引数の定義
20        Dim prm As OracleParameter = Cmd.Parameters.Add("blob", OracleDbType.Blob)
21        prm.Value = blob
22        'UPDATE文の実行
23        Dim nCnt As Integer = Cmd.ExecuteNonQuery()
24        'オラクル接続クローズ
25        Conn.Close()
26    Catch exora As OracleException
27        'オラクルエラー
28        MsgBox(exora.Number & ":" & exora.Message)
29    Catch ex As Exception
30        'PGエラー
31        MsgBox(ex.Message)
32    Finally
33        Conn.Dispose()
34    End Try
35End Sub

■BLOBデータ更新2:ODP.NET LOBオブジェクトを使用したLOBの更新

BLOBデータを更新方法のもう一つの方法は、トランザクションを開始し SELECT FOR UPDATE でBLOBデータの行を取得します。 その後、OracleDataReaderGetOracleBlobForUpdate メソッドでBLOBデータ(OracleBlob)そのものを取得します。
OracleBlob の書き込みメソッドを使ってバイト配列を設定してやります。

この処理で一つ注意点があります。SELECT文の中で取得するカラムに PRIMARY KEY を指定しないと、以下のエラーが発生します。 (以下の例では SELECT BLOB, ID FROM ... の中の ID です)
この操作の選択リストには、PRIMARY KEY、ROWIDまたはUNIQUE NOT NULL列が必要です

01'BLOBデータの更新の実行2
02Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
03    '接続文字列
04    Dim strConnect As String = _
05    "Data Source=//192.168.1.207/test; User ID=test;Password=test;"
06    'テスト画像データをバイナリ配列に読込
07    Dim fs As New System.IO.FileStream("test.png", IO.FileMode.Open, IO.FileAccess.Read)
08    Dim blobByte(fs.Length) As Byte
09    fs.Read(blobByte, 0, fs.Length)
10    'オラクル接続オブジェクト
11    Dim Conn As New OracleConnection(strConnect)
12    'トランザクションオブジェクト
13    Dim Trans As OracleTransaction = Nothing
14    Try
15        'オラクル接続オープン
16        Conn.Open()
17        'トランザクション開始
18        Trans = Conn.BeginTransaction(IsolationLevel.ReadCommitted)
19        'SELECT-SQL文
20        Dim SQL As String = "SELECT BLOB, ID FROM TT_BLOB WHERE ID = 1 FOR UPDATE"
21        'コマンドオブジェクト(SQL文と接続オブジェクト)
22        Dim Cmd As New OracleCommand(SQL, Conn)
23        Cmd.CommandType = CommandType.Text
24        'トランザクションをコマンドオブジェクトに関連付け
25        Cmd.Transaction = Trans
26        '読込オブジェクトに接続
27        Dim dr As OracleDataReader = Cmd.ExecuteReader()
28        '読込処理
29        If dr.Read Then
30            'BLOBデータの取得
31            Dim blob As Oracle.DataAccess.Types.OracleBlob = dr.GetOracleBlobForUpdate(0)
32            '読込オブジェクトのクローズ
33            dr.Close()
34            'BLOBへの書き込み
35            blob.Write(blobByte, 0, blobByte.Length)
36            'コミット
37            Trans.Commit()
38        End If
39        '読込オブジェクト廃棄
40        dr.Dispose()
41        'オラクル接続クローズ
42        Conn.Close()
43    Catch exora As OracleException
44        'ロールバック
45        Trans.Rollback()
46        'オラクルエラー
47        MsgBox(exora.Number & ":" & exora.Message)
48    Catch ex As Exception
49        'ロールバック
50        Trans.Rollback()
51        'PGエラー
52        MsgBox(ex.Message)
53    Finally
54        Conn.Dispose()
55    End Try
56End Sub

■VB.NET関連記事
「VB.NET-TIPS」ページ


share




ページのトップへ戻る