質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

3回答

4134閲覧

Webアプリケーションにfunctionの結果表示をするC#の書き方(Asp.net, Oracle)

mercredi

総合スコア26

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2016/12/09 01:47

編集2016/12/09 10:33

###前提・実現したいこと
Asp.net(c#)でOracle databaseをコネクトしてWeb applicationを作っています。(プラットフォームはVisual Studio2015 Communityです)
Sql developerでfunctionを作ったので、Web application上でユーザーにテキストボックス入力を促し、ボタンクリックでラベルにfunctionの結果表示をするC#の書き方を知りたいです。

*結果を読み取るのはデータベースに接続したままでも、Adapterを使ってDisconnectした状態でもどちらでも構いません。
ユーザーインターフェースにこだわりはありません。

###該当のソースコード
Sql (function)

create or replace function get_cAccess ( p_recipeId in number ) return char is access_type recipe.privateAccess%type; r_access recipe.privateAccess%type; begin select privateAccess into access_type from recipe where recipe_id=p_recipeId; if access_type='Y' then access_type:='N'; elsif access_type='N' then access_type:='Y'; end if; update recipe set privateAccess=access_type where recipe_id=p_recipeId returning privateAccess into r_access; return r_access; end;

Asp.netのcode behind file(C#)(抜粋)

protected void Button1_Click(object sender, EventArgs e) { using (OracleConnection conn = new OracleConnection("RecipeConnectionString")) { using (OracleCommand cmd = new OracleCommand("get_cAccess", conn)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@p_recipeId", OracleDbType.Int32).Value = TextBox1.Text; cmd.Parameters.Add("@access_r", OracleDbType.Char, 1).Direction = ParameterDirection.Output; conn.Open(); cmd.ExecuteNonQuery(); conn.Close(); Label1.Text = "Your recipe's accesstype is private 'Y': public 'N' : " + cmd.Parameters["@access_r"].Value.ToString(); } } } }

###前提・実現したいこと
ここに質問したいことを詳細に書いてください
(例)PHP(CakePHP)で●●なシステムを作っています。
■■な機能を実装中に以下のエラーメッセージが発生しました。

###発生している問題・エラーメッセージ

Webアプリケーションは表示されるのですが、P_recipeIdを入力してボタンをクリックすると、cmd.ExecuteNonQueryのところに「Oracle exception was unhandled by user 」が出ます。ちなみにWeb.configのConnectionString名は'recipeConnectionString'です。サーバーにはつながっています。あと、同じページに表示したGridviewの中のデータなどもきちんと表示されております。Functionは完成していて、Sql developer上でP_recipeIdをインプットするとr_accessはきちんとアップデートされます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/12/09 05:22

コードは ``` と ``` で囲ってください。インデントされて読みやすくなります(より多くの人が質問を読んでくれて、回答が得やすくなることが期待できます)。 現在のコードで Label1.Text には期待通りの結果が得られないのですか? どういう結果になるのでしょう? 少なくともストアドは完成していて、インプット p_recipeId に従って期待したアウトプット access_r が得られているのですか?
退会済みユーザー

退会済みユーザー

2016/12/09 12:06

質問に追記されたようですが、普通の文章まで ``` で囲われたようで、表示が見にくいので訂正してください。
guest

回答3

0

自己解決

回答していただいたみなさまありがとうございました。
今日プロフェッサーに聞いたところ、OracleはパラメーターにAddする時に一回一回変数を宣言しないといけないとのことでした。(ロジックはわからないそうです)

protected void Button1_Click(object sender, EventArgs e) { try { string connString = ConfigurationManager.ConnectionStrings["RecipeConnectionString"].ConnectionString; OracleConnection conn = new OracleConnection(connString); OracleCommand cmd = new OracleCommand(); cmd.Connection = conn; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "get_cAccess"; cmd.BindByName = true; cmd.Parameters.Add("p_recipeId", OracleDbType.Int16, ParameterDirection.Input).Value = Convert.ToInt16(TextBox1.Text); OracleParameter newpara=cmd.Parameters.Add("r_access", OracleDbType.Char, ParameterDirection.ReturnValue); newpara.Size = 1; conn.Open(); using (var dr = cmd.ExecuteReader()) { Label1.Text = cmd.Parameters["r_access"].Value.ToString(); } conn.Close(); } catch (Exception ex) { Label1.Text = "Connection doesn't open"; } }

全体的にコードを変えましたが、問題となるのは

OracleParameter newpara=cmd.Parameters.Add("r_access", OracleDbType.Char, ParameterDirection.ReturnValue); newpara.Size = 1;

ここで、SqlClientだと

cmd.Parameters.Add("r_access", OracleDbType.Char....);

で良かったんですが、オラクルだとなぜかダメだということでした。

投稿2016/12/09 22:16

mercredi

総合スコア26

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/12/10 02:04

Oracle は実際に試して検証できる環境がないので想像ですが・・・ > パラメーターにAddする時に一回一回変数を宣言しないといけない その「一回一回変数を宣言」というのは、 cmd.Parameters.Add("r_access", ... ではなくて、 OracleParameter newpara=cmd.Parameters.Add("r_access", ... のようにすると言っていると思いますが、それは違うような気がします(検証できないので気がするだけですが、もしそうなら一行上の p_recipeId パラメータの追加もそうしなければダメでは?) パラメータの宣言方法は関係なくて、前のコードにはなかった、 > cmd.BindByName = true; の追加が影響しているように思えます。 それによって、前のコードでは位置パラメータ(デフォルト・・・BindByName は false)であったものが名前指定パラメータになり、パラメータ名前を使って正しく追加されるようになったということではないかと思います。 その想像が当たっていれば cmd.Parameters.Add("r_access", ... でも問題ないはずですので、時間があれば試して結果を連絡いただけると幸いです。
退会済みユーザー

退会済みユーザー

2016/12/10 02:09

たびたびすみません。 自分が SqlClient で試した時は ExecuteReader では OUTPUT のパラメータの値は取得できず(null のまま)、ExecuteNonQuery を使う必要があったのですが、そこのところは質問者さんの場合は問題ないのでしょうか?
mercredi

2016/12/10 02:43

コメントありがとうございます。 cmd.bindByName=true;を追加した状態でパラメーターは変更せずに実行すると以前と同じエラーが出続けていたので仕方なく教授に見てもらった次第です。 ExecuteNonQuery()だとOutputでもReturnValueでもエラーが出ます。(int:type used in a using statement must be implicitly convertible to 'System.IDisposable<-いろいろ調べてみたんですが、Using(Oracle....がエラーを招いてるのでしょうか?namespaceに何かを追加しないといけないのかもしれません、ちょっと調べてみます。)ExecuteReader()だとOutputでもReturnValueでもNullではなく求めている値が帰ってきました。(Visual studioのSever explorerでfunctionを右クリックしてrunをクリックしハードコードを入れるときちんとした値が帰ってきました) ご指摘の通り問題はNullだったようで、上記の通り右クリックでハードコードを入れるとちゃんとexecuteするのに、Webアプリケーション通すとNullが帰ってくるということのようでした。実は4,5セクションで同じようなプロジェクトをしているのですが、私と同じような問題が発生したグループが多数あったようでした。私もまだプログラミングを習っている身なのでいまいちよくわかりません。お役に立てなくてすみません。
退会済みユーザー

退会済みユーザー

2016/12/10 04:10

返答いただきありがとうございました。 ODP.NET の仕様(バグ?)で訳のわからない結果になると言うような感じがしています。自分が Oracle + ODP.NET に関わる機会があるかもしれませんので、今回のことを教訓として覚えておくことにします。
mercredi

2016/12/11 12:28

そういうこともあるんですね、勉強になります。 参考までに、私と同じクラスの子は私と全く同じコードを書いて(イベントハンドラーの部分だけで、他の構成要素は全く違います)期待した値が帰ってきていました。
guest

0

ちなみにWeb.configのConnectionString名は'recipeConnectionString'です。サーバーにはつながっています。

そうであれば、まず OracleConnection("RecipeConnectionString") が間違っているように思えます。「サーバーにはつながっています」とはどういう意味でしょう?

web.config で問題の接続文字列が以下のように設定してあるとすると、

<connectionStrings> <add name="recipeConnectionString" connectionString=... /> </connectionStrings>

接続文字列は以下のようにして取得します。

string connString = System.Web.Configuration.WebConfigurationManager. ConnectionStrings["recipeConnectionString"].ConnectionString;

それを、OracleConnection のコンストラクタに以下のように設定します。

using (OracleConnection conn = new OracleConnection(connString))

そこだけが問題ではないのかもしれませんが、まずそこを訂正して試してみてください。

投稿2016/12/09 11:48

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mercredi

2016/12/09 12:50 編集

回答ありがとうございます。 サーバーにはつながってますというのは、同じページに表示されるGridviewにはテーブルデータが表示されるということでした。 ちなみのそのGridviewのデータ表示のコードです。 ``` protected void Page_Load(object sender, EventArgs e) { OracleConnection connection = new OracleConnection(WebConfigurationManager.ConnectionStrings["RecipeConnectionString"].ConnectionString); string query1 = "select recipeName, cuisine, cookingtime,ingredients_name, recipecategory,portion,direction from recipe natural join ingredients natural join recipecategory"; DataSet recipeSearchDataSet = new DataSet(); OracleDataAdapter adapter = new OracleDataAdapter(query1, connection); adapter.Fill(recipeSearchDataSet); GridView1.DataSource = recipeSearchDataSet; GridView1.DataBind(); } ``` //こちらはAdaptorを使っております。 SuferOnWwwさんのおっしゃるコードで試してみました ``` protected void Button1_Click(object sender, EventArgs e) { string connString = System.Web.Configuration.WebConfigurationManager. ConnectionStrings["recipeConnectionString"].ConnectionString; using (OracleConnection conn = new OracleConnection(connString)) { using (OracleCommand cmd = new OracleCommand("get_cAccess", conn)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("p_recipeId", OracleDbType.Int32).Value = TextBox1.Text; cmd.Parameters.Add("r_access", OracleDbType.Char, 1).Direction = ParameterDirection.Output; conn.Open(); cmd.ExecuteReader(); conn.Close(); Label1.Text = "Your recipe's accesstype is private 'Y': public 'N' : " + cmd.Parameters["r_access"].Value.ToString(); } } } ``` が、やっぱり同じエラーが出てしまいます。せっかく教えてくださったのにすみません。。。 ちなみにWeb.configのconnectionStringですが ``` <add name="RecipeConnectionString" connectionString="DATA SOURCE=..../> ``` このような感じになっております。
mercredi

2016/12/09 12:24

コメントとコードが入り乱れてますね。初心者なものですみません。シングルクォテーション3つで囲んでみたんですが。。。
mercredi

2016/12/09 12:54

コメントの表示方法をいろいろ試してみましたが、ちょっとわからないので後ほど修正いたします。(今から学校行く準備をしなければいけないので)
退会済みユーザー

退会済みユーザー

2016/12/09 13:03

接続文字列の設定以外のコードも変えましたね。ExecuteReader はダメなのでは? 元に戻して ExecuteNonQuery にしたらどうなりますか?
退会済みユーザー

退会済みユーザー

2016/12/09 13:06

コメント欄は ``` は効かないようです。
mercredi

2016/12/09 13:12

表示方法を直してないのに回答してくださってありがとうございます。すみません、いろいろ試しててコードを元に戻すの忘れてました。ExecuteNonQuery()でもダメです。ただ、新しいエラーがでました。 ``` ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'CHANGE_TO_HOUR' ORA-06550: line 1, column 7: PL/SQL: Statement ignored ``` 元々のテーブルのrecipe_idコラムのデータタイプはnumberです。(SequenceでGenerateしたプライマリーキーです)、ただパラメーターをAddする時にOracleDbTypeだと整数型がInt32(Int16, Int64)しかなかったのでOracleDbType.Int32でパラメーターをAddしました。
mercredi

2016/12/09 13:13

あーなるほどそうなんですか。ありがとうございます。
mercredi

2016/12/09 13:34

補足:相変わらず(Oracle exception was unhandled by user)は同じ場所(ExecuteNonQuery())に出ています。
退会済みユーザー

退会済みユーザー

2016/12/09 13:48

"wrong number or types" というエラーメッセージからの想像・思いつきですが、 cmd.Parameters.Add("p_recipeId", OracleDbType.Int32).Value = TextBox1.Text; の TextBox1.Text は string 型なのですが、それを Parse して Int32 型にしたから代入したらどうなりますか?
mercredi

2016/12/09 14:11

cmd.Parameters.Add("p_recipeId", OracleDbType.Int32).Value = int.Parse(TextBox1.Text); これでやってみましたがダメです。同じエラーが出ます。
guest

0

上記のコードで何を問題にしているのか記載がないので、わからない点躓いている点を書いて頂きたいのですが....

ADO.NETを使っているという認識でよいでしょうか。であれば、
質問で書かれているExecuteNonQueryはクエリを実行するためのものです。
データを取得したいのであれば、ExecuteReaderメソッドなど、戻り値を受け取るメソッドを使いましょう。

コードサンプルはMSDNのこちらにありますので、十分参考になるかと思います。

投稿2016/12/09 05:13

BEACHSIDE

総合スコア294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/12/09 05:58

横から失礼します。 ストアドが OUTPUT としてパラメータ r_access を渡せるようになっていて(質問者さんのコードでそうなっているかは分かりませんが)、ASP.NET のコードの方でそのパラメータを受け取るようにコーディングされていれば、ExecuteNonQuery でよいはすですが?
BEACHSIDE

2016/12/09 06:10

はっ!ストアドとか`CommandType `の設定見ないでC#の接続部分見てに応えてました。(最近適当にみることが多くてあかんと思ってます)仕事の隙間縫ってみようと思ったら質問者に迷惑かけちゃいますね。ご指摘ありがとうございます♪ この文章意味ないので、今日の夜には消しますね。(SurferOnWwwさんにありがとう言うためにちょっとだけ残しておきます♪mercrediさん失礼しました。) 本題にちょっと触れると、 ストアドが間違っているのか、そもそもDB接続に問題あるのか切り分ければ解決しそうですね。SurferOnWwwさんの指摘や私の文章の最初にも書きましたが、何が問題かエラーとかあるのか書いていただけれと思います。
mercredi

2016/12/09 11:04

Beachsideさん、SurferOnWwwさんありがとうございます。 さっきお礼を投稿したのですが、なぜか表示されておりません。2重投稿になってたらすみません。
mercredi

2016/12/09 11:11

今回は表示されたみたいなので、少し詳細を。 ご指摘の通りADO.netを使っております。ExecuteReader()でエラーが出たのでExecuteNonQuery()にしたのですが、同じエラー(Oracle exception was unhandled by user)が出てしまいました。 functionはSql developer上ではp_recipeIdを入力すると求められた結果が得られます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問