@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

OleDbDataReaderでストアドプロシージャで実行した検索結果を読み込みたい。

投稿者投稿内容
たけたけ
会議室デビュー日: 2003/05/27
投稿数: 7
投稿日時: 2003-07-12 18:07
こんにちは。いつも拝見させてもらっています。

今、C#.NETでOracleに登録されてるテーブル内のデータを
ストアドプロシージャを実行して読み込み、
Web画面に表示させるプログラムを作ってるのですが、
どうすればストアドプロシージャからの読込みデータを取得できるのかが
分りません。すいませんがご教示よろしくお願い致します。

★環境は以下になります。
OS  :Windows2000
言語 :C#
プロバイダracle Provider for OLE DB

★作成条件は以下になります。
OleDbDataReaderを使用してデータを1件ずつ取得する。

★分らない事1
例えば下記SQLの実行結果が複数行有る場合、
この結果をOleDbDataReaderを使用してデータを1件づつ取得するには、
Oracleに登録するストアドプロシージャの内容にはどんな書き方が
必要になるのでしょうか?

SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO
FROM EMP
WHERE EMPNO = パラメータ1

★分らない事2
C#で上記プロシージャを呼び出す為の記述方法が分りません。

★分らない事3
本件の内容とはちょっと違うのですが、
OleDbDataReaderを使用してる場合、現在のOleDbDataReaderのCLOSEを行わずに
別のSQLの検索結果を取得することは本当にできないのでしょうか?
そんなことが下記URLに書かれていたので。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpcontheadonetdatareader.asp

では一つのコネクションでOleDbDataReaderを使用してAテーブルの検索結果を
1件取得して、その検索結果を使用してBテーブルの検索結果を取得すると
入れ子になってるような場合はどうすればよいのでしょうか?
<イメージ例>
OleDbDataReader data1;
OleDbDataReader data2;
for( data1.Read() )
{
<データ取得処理1>

for(data2.Read() )
{
<データ取得処理2>
}
}

★調べた事
色々ここに載せるまでに自分で調べてみたのですが、
どうも今一つはっきりと分らないし、参考に作成してみても
上手くいかないのです。
このURLに一番詳しく記述されてるようなのですが、
http://support.microsoft.com/default.aspx?scid=kb;ja;309361
今いち内容が把握できませんでした。


すいませんが、皆さんのお力添えをよろしくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-07-16 15:27
引用:

たけたけさんの書き込み (2003-07-12 18:07) より:

今、C#.NETでOracleに登録されてるテーブル内のデータを
ストアドプロシージャを実行して読み込み、
Web画面に表示させるプログラムを作ってるのですが、
どうすればストアドプロシージャからの読込みデータを取得できるのかが
分りません。すいませんがご教示よろしくお願い致します。



 Oracleのマニュアルも参照してください。
『Oracle Provider for OLE DB開発者ガイド リリース9.2』J06332-01.pdf
→2−12ページ「複数の行セット」

引用:

★分らない事1
Oracleに登録するストアドプロシージャの内容にはどんな書き方が
必要になるのでしょうか?


PACKAGE TEST_PACKAGE AS
TYPE r_cursor IS REF CURSOR;←
PROCEDURE ListUp(param1 AS INTEGER, v_cursor OUT r_cursor);←
END TEST_PACKAGE;

PACKAGE BODY TEST_PACKAGE IS
PROCEDURE ListUp(param1 AS INTEGER, v_cursor OUT r_cursor) IS←
BEGIN
OPEN v_cursor FOR SELECT EMPNO, ENAME, JOB, MGR
, HIREDATE, SAL, COMM, DEPTNO FROM EMP WHERE EMPNO = param1;←
END ListProducts;
END TEST_PACKAGE;

引用:

★分らない事2
C#で上記プロシージャを呼び出す為の記述方法が分りません。


すみません、VBなので、直してください。
Dim con As OleDbConnection
Dim cmd As OleDbCommand
Dim rd As OleDbDataReader

Try
con = New OleDbConnection("Provider=OraOLEDB.Oracle" _
& ";Data Source=DATA_SOURCE;User ID=USER;Password=PASSWORD" _
& ";Persist Security Info=True;OLEDB.NET=True" _
& ";PLSQLRSet=True" _ ←この設定が絶対にいる
& ";Extended Properties=""""")
cmd = New OleDbCommand("{CALL TEST_PACKAGE.ListUp(?)}", con)
cmd.Parameters.Add("PARAM1", OleDbType.Integer).Value = 値←
con.Open()
rd = cmd.ExecuteReader
While rd.Read
ListBox1.Items.Add(rd.GetString(0))←
End While
rd.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, ex.GetType.ToString)
Finally
con.Close()
End Try

さらにすみません。
私、引数なしを作ったので、Parameters.Add()の所、適宜書き直してください。
『←』入れているところ、要注意です。
rd.GetString()の引数は、SELECTで指定した列の数有効です。
GetXXXは、列の型にあわせてください。
たけたけ
会議室デビュー日: 2003/05/27
投稿数: 7
投稿日時: 2003-07-17 12:18
こんにちは。Jittaさん。
Jittaさんには以前にもお世話になりました。
今回も返答ありがとうございます。

返信の例を試したところ上手くいきました。
プロシージャ側で出力の引数を指定してるのに
呼び出し側のアプリでは指定しなくていいこと
にちょっとびっくりしました。
それから開発者ガイドを読むとPLSQLRsetのtrueセットが
必要と書かれてるのに自分は別のサンプルを鵜呑みにしてて
設定もしてませんでした(-_-反省。

詳しく書いて頂いて大変助かりました。m(__)m
ありがとうございました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-07-18 22:03
引用:

たけたけさんの書き込み (2003-07-17 12:18) より:
プロシージャ側で出力の引数を指定してるのに
呼び出し側のアプリでは指定しなくていいこと
にちょっとびっくりしました。
それから開発者ガイドを読むとPLSQLRsetのtrueセットが
必要と書かれてるのに自分は別のサンプルを鵜呑みにしてて
設定もしてませんでした(-_-反省。


 そうなんですよね。Oracleのマニュアルには、引数4つ、
うち2つがOUTの例が載っていたのですが、しかもADO、
同じようにして通ったので、「とりあえず、いいか」という感じ。

もう一つ、どこかで引数に配列を指定する方法もあったはずなので、
それも探しておきます・・・つまり、私も必要なんです(^^;
たけたけ
会議室デビュー日: 2003/05/27
投稿数: 7
投稿日時: 2003-07-20 20:43
返答が遅くなりました。
Jittaさんも同じような開発をやってるのですか?
自分が今回携わってるシステムでは、SQLの実行は全てストアドプロシージャでと
決められていてJittaさんが言うような配列のパラメータ入出力などでの部分でも悩んでます。
どこかに載ってるのですか?
Oracle Provider for OLE DBを使用した例って少ないですよね。

すいません。ここから別の質問になるのですが、
このプロバイダでコネクションプールとかは使えるんですか?
調べてるとこのプロバイダではコネクションプールは使えないではと心配しています。

後、データベースサーバからのデータ読み取りが1回で終わる方法なんてないのでしょうか?
DataReaderを使用して1件、1件、データベースサーバからデータを読み取るのは効率が悪いと思うのです。
またDataReaderは資料によると一度使用すると、Connection Closeまでしないと
ダメだと書かれてるんですよね。
別の検索SQLを実行する度にConnectするのも効率悪いな感じるのです。
Jittaさんはこの辺の部分はどうされていますか?

質問ばかりでスイマセンがよろしくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-07-22 09:12
とりあえず、すぐわかるところだけ。

>Jittaさんも同じような開発をやってるのですか?
 データベース使う部分は、たいてい一緒でしょ
 SQL ServerとOracleの両方をサポートするため、
できるだけストアドプロシージャにしたいのですが、
ストアドプロシージャでのプログラミング経験が皆無なので手こずっています。


>配列のパラメータ入出力などでの部分でも悩んでます。
>どこかに載ってるのですか?
 載っています。どこかで見かけました。現在捜索中・・・


>このプロバイダでコネクションプールとかは使えるんですか?
 特に指定しなくても、プールされているようです。
いくつ、かはわかりません。これもMSDNに載っていたと思います。
たけたけ
会議室デビュー日: 2003/05/27
投稿数: 7
投稿日時: 2003-07-22 11:10
私もマニュアルやネットなどをよく調査してみます。
まだまだ、やりたい事に対して分らない事が山積みで(;_;)
何度もお答え頂いてありがとうござました。

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-07-22 12:11
失礼しました。
「Oracle Data Provider for .NET」
「Oracle Provider for OLE DB」
「OLE DB for .NET」
「.NET Framework Data Provider for Oracle」
の情報がごちゃ混ぜになっていました。↑名前からして紛らわしい


コネクションプーリングは「ODP for .NET」「.NET FDP for Oracle」でした。
これらは自動でプーリングの管理をしてくれます。


配列は「OLE DB for .NET」+「MSDAORA」でした。
この情報は「.NET FDP for Oracle」のドキュメントに書かれています。
また、オラクル側の資料からは見つけられませんでした。
おそらく、配列よりもREF CURSORを使用する方が効率が良いためと思われます。
#この判断は、MSDN ライブラリ Visual Studio .NET 2003リリースの、
#「System.Data.OracleClient名前空間」の記述によります。
引用:

PL/SQL の TABLE データ型は、Oracle .NET Framework データ プロバイダではサポートされていません。ただし、 REF CURSOR データ型の方がより効率的です。 TABLE データ型を使用する必要がある場合は、MSDAORA と共に OLE DB .Net データ プロバイダを使用してください。

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