- PR -

ODP.NET 経由でファンクション戻り値を取得する

投稿者投稿内容
ケビン
会議室デビュー日: 2007/04/12
投稿数: 15
投稿日時: 2007-05-23 07:37
VS2005 を使用し、ODP.NET 経由で、Oracle10g に接続していますが、
発行する select 文中で、BLOB 型の値を返すファンクションを記述したとき、
OracleDataReader では、RAW 型として暗黙な型変換を行っているらしく、
レスポンスが著しく低下してしまっています。

OTNをはじめ、色々と調べてみましたが行き詰ってしまい、困っています。
宜しくお願いします。
YASUYOKA
ベテラン
会議室デビュー日: 2007/03/19
投稿数: 71
投稿日時: 2007-05-23 10:03
引用:

ケビンさんの書き込み (2007-05-23 07:37) より:
VS2005 を使用し、ODP.NET 経由で、Oracle10g に接続していますが、



VBですか?C#ですか?VC++ですか?

引用:

発行する select 文中で、BLOB 型の値を返すファンクションを記述したとき、
OracleDataReader では、RAW 型として暗黙な型変換を行っているらしく、
レスポンスが著しく低下してしまっています。



SELECT文を発行する時のVS側のコードと、SQL文を差し支えない程度に詳しく
記載願います。

引用:

OTNをはじめ、色々と調べてみましたが行き詰ってしまい、困っています。



USのOTNサイトに「Populate DataSet, DataReader with LOB Sample」という
サンプルがありますが、参考にはなりませんか?
http://www.oracle.com/technology/sample_code/tech/windows/odpnet/odpbasic.html
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-05-23 11:14
SQLを見てみないとなんとも言えませんが、
ODPの問題というよりは Oracle の問題に思えます。
SELECT句の中で CAST 関数で変換してあげたら上手くいきませんか?

SELECT CAST(関数名() AS BLOB)

みたいに。
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-05-23 11:29
引用:

ケビンさんの書き込み (2007-05-23 07:37) より:
VS2005 を使用し、ODP.NET 経由で、Oracle10g に接続していますが、
発行する select 文中で、BLOB 型の値を返すファンクションを記述したとき、
OracleDataReader では、RAW 型として暗黙な型変換を行っているらしく、
レスポンスが著しく低下してしまっています。



■ BLOG のフィールドを返すのは Oracle の関数ですか?
それとも .NET のメソッドですか?

■ BLOB のフィールドを取得する .NET のコードを掲載できたらお願いします。

■ レスポンスが低下するというのは何と比べてどの程度手化するのでしょうか?

引用:

OTNをはじめ、色々と調べてみましたが行き詰ってしまい、困っています。
宜しくお願いします。


いろいろ調べたなら、調べた痕跡を記入したほうがいいです。
同じ URL をアドバイスしても双方に時間の無駄ですから。
_________________
かるあ のメモスニペット
ケビン
会議室デビュー日: 2007/04/12
投稿数: 15
投稿日時: 2007-05-23 11:57
情報が不足しておりまして申し訳ございません。


■ ORACLE の ファンクション(SAMPLE_PKG パッケージに記述)

  FUNCTION GET_BLOB(value IN NUMBER)
RETURN BLOB
IS
ret_value BLOB;
BEGIN
ret_value := TO_BLOB('ABC');
RETURN ret_value;
END GET_BLOB;


■ ODP.NET から発行する SQL 文

SELECT SAMPLE_PKG.GET_BLOB(1) FROM DUAL;


OracleDataReader reader = command.ExecuteReader();

  if (!reader.IsClosed && reader.HasRows)
{
// 全データを読みまわす
while (reader.Read())
{
if (!reader.IsDBNull(0))
{
OracleBlob blob = reader.GetOracleBlob(0); // ← <※>BLOB取得
}
}
}


上記で、<※>の部分を通ると内部エラーとなってしまいます。
ODP.NET での暗示的な型変換に引っかかっているような気がするのですが、
この部分を、RAW 型のデータを取得する GetOracleBinary() メソッドに書き換えると
正常に値を取ることができます。
BLOB 型のフィールドのデータを、select 文で取得する場合は問題なく、
また高速(1万件で1秒程度)で読み取ることができます。
しかし、ファンクションの出力で BLOB 型の値を取得するときは、
RAW 型への型変換が働いているためか、1万件のデータを読み取るのに、
25 秒以上もかかってしまいます。
色々と試行錯誤していますが答えが見つかっていません。

ちなみに、CAST 構文を使ってみましたが、SQL の実行エラーとなります。
BLOB データを BLOB に変換しようとしている例外でした。

最後に、実行した SQL を、Oracle上で実行した場合についてですが、
復帰値については、BLOB 型で返されていることが確認できています。
Oracle SQL Developer を使用して確認しました。


かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-05-23 13:43
何度か紹介しているので、すでにご覧になっているかもしれませんが@ITのこの記事は参考にしましたか?
http://www.atmarkit.co.jp/fdb/rensai/odpdotnet03/odpdotnet03_1.html

関係ないかもしれませんが、Oracleのファンクションが単一の値を返すなら、ExecuteReader ではなく ExecuteScalar で値を返したらどうなりますか?
_________________
かるあ のメモスニペット
ケビン
会議室デビュー日: 2007/04/12
投稿数: 15
投稿日時: 2007-05-23 14:05
> かるあ さん

紹介ページについては既に拝見しております。
あと、ExecuteScalar では正しく取得できています。
っが、本当に BLOB 型として取得したのかどうかはわかりません。
ODP.NET 側で暗黙的な型変換が働いた可能性があります。

但し、本来やりたいことは単一行を取得することではなく、
テーブルの項目と、テーブルの項目を入力として BLOB 型の出力値を
返すファンクションの値を N 件取得することなので、
ExecuteReader か RefCursor を使う方法になると思っています。

サンプルプログラムは BLOB 型を返すファンクションから、
きちんと BLOB 型で返されるか、という検証をするためのもので、
あえて単一行を返すようにしています。
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-05-23 15:44
ありゃ、僕も RefCursor に対して GetOracleBlob したら ORA-3001 が発生してしまいました。
確かに暗黙の型変換あたりが起きている感じはしますね。

ちょっと試してみました。
RefCursor で取得するからダメっぽいです。
Oracle の Package 側で RefCursor でなく、静的なカーソルとして定義すると GetOracleBlob() で取得することができました。
Oracle Package
コード:
  -- CURSOR imgCur IS REF CURSOR;
  CURSOR c IS SELECT * FROM IMAGE_TABLE;
  TYPE imgCur IS REF CURSOR RETURN c%ROWTYPE;
  FUNCTION GetImage() RETURN imgCur

スキルアップ/キャリアアップ(JOB@IT)