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

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

ただいまの
回答率

90.34%

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,791

mercredi

score 24

前提・実現したいこと

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はきちんとアップデートされます。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2016/12/09 14:22

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

    キャンセル

  • 退会済みユーザー

    2016/12/09 17:31

    こちらの質問が他のユーザから「問題・課題が含まれていない質問」という指摘を受けました
    teratailでは、漠然とした興味から票を募るような質問や、意見の主張をすることを目的とした投稿は推奨していません。
    「編集」ボタンから編集を行い、質問の意図や解決したい課題を明確に記述していただくと回答が得られやすくなります。

  • SurferOnWww

    2016/12/09 21:06

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

    キャンセル

回答 3

check解決した方法

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/10 11: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 13:10

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

    キャンセル

  • 2016/12/11 21:28

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

    キャンセル

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/09 14:58

    横から失礼します。

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

    キャンセル

  • 2016/12/09 15:10

    はっ!ストアドとか`CommandType `の設定見ないでC#の接続部分見てに応えてました。(最近適当にみることが多くてあかんと思ってます)仕事の隙間縫ってみようと思ったら質問者に迷惑かけちゃいますね。ご指摘ありがとうございます♪

    この文章意味ないので、今日の夜には消しますね。(SurferOnWwwさんにありがとう言うためにちょっとだけ残しておきます♪mercrediさん失礼しました。)

    本題にちょっと触れると、
    ストアドが間違っているのか、そもそもDB接続に問題あるのか切り分ければ解決しそうですね。SurferOnWwwさんの指摘や私の文章の最初にも書きましたが、何が問題かエラーとかあるのか書いていただけれと思います。

    キャンセル

  • 2016/12/09 20:04

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

    キャンセル

  • 2016/12/09 20:11

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

    キャンセル

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 22:34

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

    キャンセル

  • 2016/12/09 22:48

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

    キャンセル

  • 2016/12/09 23:11

    cmd.Parameters.Add("p_recipeId", OracleDbType.Int32).Value = int.Parse(TextBox1.Text);

    これでやってみましたがダメです。同じエラーが出ます。

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る