前提・実現したいこと
Oracle11gでPROCEDUREを作成しました。
OUTパラメータとして、TYPEをしていしております。
C#プログラムからこのPROCEDUREを呼び出したときにOUTパラメータを受け取り、
結果表示したいと考えております。
発生している問題・エラーメッセージ
PROCEDUREを呼び出した際にOUTパラメータの受け取り時にエラーが発生します。
「'TB_P_TEST'の呼出しで、引数の数または型が正しくありません。」
OUTパラメータを受け取り方がわかっておりません。
該当のソースコード
【Oracle側】
<TYPE>
CREATE OR REPLACE TYPE TB_T_KAIKOBI FORCE AS OBJECT ( sKaikobi VARCHAR2(8), iTeiinCheck NUMBER(1,0) ) /
CREATE OR REPLACE TYPE TB_T_KAIKOBI_A FORCE AS TABLE OF TB_T_KAIKOBI /
<PROCEDURE>
CREATE OR REPLACE PROCEDURE TB_P_TEST ( p_in_iBumon IN NUMBER , p_out_aKaikobi OUT TB_T_KAIKOBI_A ) IS infoKaikobi TB_T_KAIKOBI; BEGIN /* 返り値セット */ p_out_aKaikobi := TB_T_KAIKOBI_A(); p_out_aKaikobi.extend(2); --2コの配列 --開講日情報の1つ目の要素(1-1-1) infoKaikobi := TB_T_KAIKOBI('20201112',0); p_out_aKaikobi(1) := infoKaikobi; --開講日情報の2つ目の要素(1-1-2) infoKaikobi := TB_T_KAIKOBI('20201113',1); p_out_aKaikobi(2) := infoKaikobi; COMMIT; END; /
※INパラメータの「p_in_iBumon」は実際には使用しますが、
テストPROCEDUREでは使用しなくしております。
【C#側】
private void btnTest_Click(object sender, EventArgs e) { List<object> listValue = new List<object>(); listValue.Add(1); List<OleDbParameter> listInitOut = GetProcedure(listValue, "TB_P_TEST"); } /// <summary> /// プロシージャ情報の取得 /// </summary> public List<OleDbParameter> GetProcedure(List<object> listValue, string strProcedure) { //データベースの接続先を指定 using (OleDbConnection OraConn = new OleDbConnection(/*接続先文字列*/)) { using (OleDbCommand Cmd = new OleDbCommand()) { //データベース接続を開く OraConn.Open(); Cmd.Connection = OraConn; //コマンドタイプをストアドプロシージャにする Cmd.CommandType = CommandType.StoredProcedure; //実行するストアドプロシージャを指定 Cmd.CommandText = strProcedure; //ストアドプロシージャのin用パラメータ作成 List<string> listInName = new List<string>(); List<OleDbType> listInType = new List<OleDbType>(); listInName.Add("1"); listInType.Add(OleDbType.Decimal) //Inパラメータの追加 int intInPrameter = 0; foreach (string strName in listInName) { Cmd.Parameters.Add(strName, listInType[intInPrameter]).Value = listValue[intInPrameter]; intInPrameter++; } //ストアドプロシージャのout用パラメータ作成 List<OleDbParameter> listOutpara = new List<OleDbParameter>(); //リストのタイプを作成 List<string> listOutName = new List<string>(); List<OleDbType> listOutType = new List<OleDbType>(); OutParamInfo outInfo = new OutParamInfo(); listOutName.Add("開講日情報"); //←ここのセット方法がどのようにすればよいかがわかっておりません listOutType.Add(OleDbType.Binary); //←ここのセット方法がどのようにすればよいかがわかっておりません //Outパラメータの追加 int intOutPrameter = 0; foreach (string strName in listOutName) { OleDbParameter outPara = new OleDbParameter(strName, listOutType[intOutPrameter]); outPara.Direction = ParameterDirection.Output; outPara.Size = 40; listOutpara.Add(outPara); Cmd.Parameters.Add(outPara); intOutPrameter++; } //ストアドプロシージャの実行 Cmd.ExecuteNonQuery(); return listOutpara; } } }
上記からODP.NETを使用したソースに変更しました。
TYPEを使用しないPROCEDUREの場合、成功しました。
以下は配列をやめてみて、TYPEのみの受け渡しを記載しました。
実行すると「Cmd.ExecuteNonQuery(); 」の部分でエラーが発生します。
TYPEでない場合、成功するので、listOutType.Add(OracleDbType.Object); が
悪いのか、「listOutName.Add("p_out_Kaikobi"); 」の設定が悪いと思っております。
バインディングというのがピンときておりません。
CREATE OR REPLACE PROCEDURE TB_P_TEST2 ( p_in_iBumon IN NUMBER , p_out_Kaikobi OUT TB_T_KAIKOBI ) IS BEGIN /* 返り値セット */ p_out_Kaikobi := TB_T_KAIKOBI('20201112',0); COMMIT; END; /
private void btnTest_Click(object sender, EventArgs e) { List<object> listValue = new List<object>(); listValue.Add(1); List<OracleParameter> listInitOut = GetProcedure(listValue, "TB_P_TEST2"); } /// <summary> /// プロシージャ情報の取得 /// </summary> public List<OracleParameter> GetProcedure(List<object> listValue, string strProcedure) { //データベースの接続先を指定 OracleConnection OraConn = new OracleConnection(); OraConn.ConnectionString = /*接続先文字列*/; OraConn.Open(); OracleCommand Cmd = new OracleCommand(); //データベース接続を開く OraConn.Open(); Cmd.Connection = OraConn; //コマンドタイプをストアドプロシージャにする Cmd.CommandType = CommandType.StoredProcedure; //実行するストアドプロシージャを指定 Cmd.CommandText = strProcedure; //ストアドプロシージャのin用パラメータ作成 List<string> listInName = new List<string>(); List<OracleDbType> listInType = new List<OracleDbType>(); listInName.Add("1"); listInType.Add(OracleDbType.Decimal) //Inパラメータの追加 int intInPrameter = 0; foreach (string strName in listInName) { Cmd.Parameters.Add(strName, listInType[intInPrameter]).Value = listValue[intInPrameter]; intInPrameter++; } //ストアドプロシージャのout用パラメータ作成 List<OracleParameter> listOutpara = new List<OracleParameter>(); //リストのタイプを作成 List<string> listOutName = new List<string>(); List<OracleDbType> listOutType = new List<OracleDbType>(); OutParamInfo outInfo = new OutParamInfo(); listOutName.Add("p_out_Kaikobi"); //←ここのセット方法がどのようにすればよいかがわかっておりません listOutType.Add(OracleDbType.Object); //←Objectに変更したところ、型が正しくありませんは解消されました //Outパラメータの追加 int intOutPrameter = 0; foreach (string strName in listOutName) { OracleParameter outPara = new OracleParameter(strName, listOutType[intOutPrameter]); outPara.Direction = ParameterDirection.Output; outPara.Size = 40; listOutpara.Add(outPara); Cmd.Parameters.Add(outPara); intOutPrameter++; } //ストアドプロシージャの実行 Cmd.ExecuteNonQuery(); //←ここで「p_out_Kaikobi」バインディングが無効ですとなります。 return listOutpara; } } }
試したこと
「OleDbType」を「Binary」としておりますが、他の値でも一通り試してみました。
ネット調べてもC#で%TYPEの取得方法が見つからず、苦慮しております。
補足情報(FW/ツールのバージョンなど)
開発環境は以下の通り
C#
Oracle11g
.Net3.5



回答2件
あなたの回答
tips
プレビュー