DOBON.NETプログラミング道掲示板
(現在 過去ログ1 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33016 / inTopicNo.1)  C#からストアドの実行
  
□投稿者/ み 一般人(3回)-(2015/07/02(Thu) 15:16:22)
  • アイコン環境/言語:[WIN7 .net4.5 vs2012] 
    分類:[.NET] 

    お世話になっております。
    下記URLを参考にC#からストアドを実行して結果を返すコードを書きました。
    https://code.msdn.microsoft.com/windowsdesktop/DataAccess-howto-32c91bf0
    
    しかし以下のエラーになりました。
    プロシージャまたは関数 'ap_TEST' にはパラメーター '@P1' が必要ですが、指定されませんでした。
    
    下記コードです。
    宜しくお願い致します。
    ■ストアド
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER PROCEDURE [dbo].[ap_TEST]
    	@P1 VARCHAR(10),
    	@P2 VARCHAR(10)
    
    AS
    BEGIN
    
    	DECLARE @CNT INT = 0
    
    	SELECT  @CNT = count(*) FROM S_USER
    	WHERE USERID = '@P1' and PASSWORD = '@P2'
    
    	RETURN @CNT
    
    END
    
    ■C#コード
    
          public static int ExecuteStored(string cSqlConnection, string userid, string pass)
            {
    
                int returnValue = 0;
    
                using (SqlCommand command = new SqlCommand())
                {
                    SqlConnection conn = new SqlConnection(cSqlConnection);
                    conn.ConnectionString = cSqlConnection;
    
                    conn.Open();
                    SqlCommand cmd = new SqlCommand("ap_TEST", conn);
    
                    SqlCommand hCommand = conn.CreateCommand();
    
                    try
                    {
                        command.CommandType = CommandType.StoredProcedure;
    
                        //パラメータ1
                        cmd.Parameters.Add(new SqlParameter("P1", SqlDbType.Text));
                        cmd.Parameters["P1"].Direction = ParameterDirection.Input;
                        cmd.Parameters["P1"].Value = userid;
    
                        //パラメータ2
                        cmd.Parameters.Add(new SqlParameter("P2", SqlDbType.Text));
                        cmd.Parameters["P2"].Direction = ParameterDirection.Input;
                        cmd.Parameters["P2"].Value = pass;
    
                        //戻り値
                        cmd.Parameters.Add(new SqlParameter("ReturnValue", SqlDbType.Int));
                        cmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
    
                        SqlDataReader dr = cmd.ExecuteReader();
                        while (dr.Read())
                        {
                            Console.WriteLine("結果セット:" + dr[0]);
                        }
                        dr.Close();
    
                        returnValue = ((int)cmd.Parameters["ReturnValue"].Value); 
    
    
                    }
                    catch (System.Exception)
                    {
                        throw;
                    }
                    finally
                    {
                        conn.Close();
                    }
    
                    return returnValue;
                }
    
            }
    −−−ここまで
    
    
    

引用返信 削除キー/
■33019 / inTopicNo.2)  Re[1]: C#からストアドの実行
□投稿者/ しま 一般人(11回)-(2015/07/02(Thu) 16:11:18)
  • アイコン2015/07/02(Thu) 16:13:55 編集(投稿者)

    No33016に返信(みさんの記事)
    > お世話になっております。

    いえいえ、お世話した覚えはないです。
    > 下記URLを参考にC#からストアドを実行して結果を返すコードを書きました。
    > https://code.msdn.microsoft.com/windowsdesktop/DataAccess-howto-32c91bf0
    >
    > しかし以下のエラーになりました。
    > プロシージャまたは関数 'ap_TEST' にはパラメーター '@P1' が必要ですが、指定されませんでした。
    >

    環境はきちんと書いてください SQLServer のバージョン、エディションなども忘れずにお願いします。見ず知らずの他人に読ませると言うことを考えて書きましょう。
    まず、どこまで動作試験なさったのでしょうか。
    ストアードプロシジャー ap_TEST の SQL Server 上での動作試験はなさいましたか?
    >WHERE USERID = '@P1' and PASSWORD = '@P2'
    はどこか変に思いますが判りますでしょうか?
    '@P1' は @P1 と言う文字列であって、引数 @P1 とは異なります

    また、エラーメッセージで @P1 という引数名が必要だと言われていうるのですから、 C# からのストアードプロシジャー ap_TEST の呼出で引数名を @P1 にしてみてはいかがでしょうか?

引用返信 削除キー/
■33020 / inTopicNo.3)  Re[2]: C#からストアドの実行
□投稿者/ しま 一般人(12回)-(2015/07/02(Thu) 16:16:28)
  • アイコンNo33019に返信(しまさんの記事)
    > ■No33016に返信(みさんの記事)
    >>お世話になっております。
    >
    > はどこか変に思いますが判りますでしょうか?
    > '@P1' は '@P1' と言う文字列であって、引数 @P1 とは異なります
    '@P1' は @P1 と言う文字列であって、引数 @P1 の値とは異なります

    の間違いです。
引用返信 削除キー/
■33021 / inTopicNo.4)  Re[1]: C#からストアドの実行
□投稿者/ 魔界の仮面弁士 大御所(976回)-(2015/07/02(Thu) 16:17:11)
  • アイコンNo33016に返信(みさんの記事)
    > WHERE USERID = '@P1' and PASSWORD = '@P2'
    上記は、
     WHERE USERID = @P1 and PASSWORD = @P2
    では無いでしょうか?

    C# 側でいえば、
     if (this.textBox1.Text == strData)
     if (this.textBox1.Text == "strData")
    の違いのようなもので。


    > using (SqlCommand command = new SqlCommand())
    > SqlCommand cmd = new SqlCommand("ap_TEST", conn);
    > SqlCommand hCommand = conn.CreateCommand();

    SqlCommand の変数を、何故 3 つも用意されているのでしょうか?
    特に「hCommand」に至っては、意図がさっぱり…。

    「command」は .CommandType = CommandType.StoredProcedure を
    設定していますが、これも実際には未使用ですよね。


    本題となる「cmd」は、パラメータ設定こそされているものの、
     cmd.CommandType = CommandType.StoredProcedure;
    が設定されていないのが最大の問題点です。
    その点を修正すれば前進するでしょう。

    まぁ、CommandType が初期値のままであっても
     SqlCommand cmd = new SqlCommand("ap_TEST P1, P2", conn);
    という構文にすれば一応認識されるのですが(この場合、戻り値は破棄)、
    肝心のパラメータが「VarChar, 10」ではなく「Text」になっているので、
    この点も修正しておいた方が良いでしょうね。
引用返信 削除キー/
■33022 / inTopicNo.5)  Re[3]: C#からストアドの実行
□投稿者/ み 一般人(4回)-(2015/07/02(Thu) 17:25:21)
  • アイコン
    しまさん 魔界の仮面弁士さん返信ありがとうございます。
    いろいろコピペして無駄なコードになっていました。
    また指摘を受けて以下のコードに修正しました。
    ストアド側はそのままです。
    SQL-Serverは2012devバージョンです。
    結果としてヒットして1件返りました。
    
    
            public static int ExecuteStored(string cSqlConnection, string userid, string pass)
            {
    
                int returnValue = 0;
    
                using (SqlConnection conn = new SqlConnection(cSqlConnection))
                {
                    try
                    {
                        conn.ConnectionString = cSqlConnection;
                        conn.Open();
    
                        using (SqlCommand cmd = new SqlCommand("ap_TEST", conn))
                        {
    
                            cmd.CommandType = CommandType.StoredProcedure;
    
                            cmd.CreateParameter();
                            //パラメータ1
                            cmd.Parameters.Add(new SqlParameter("@P1", SqlDbType.VarChar));
                            cmd.Parameters["@P1"].Direction = ParameterDirection.Input;
                            cmd.Parameters["@P1"].Value = userid;
    
                            //パラメータ2
                            cmd.Parameters.Add(new SqlParameter("@P2", SqlDbType.VarChar));
                            cmd.Parameters["@P2"].Direction = ParameterDirection.Input;
                            cmd.Parameters["@P2"].Value = pass;
    
                            //戻り値
                            cmd.Parameters.Add(new SqlParameter("ReturnValue", SqlDbType.Int));
                            cmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
                            cmd.ExecuteReader();
    
                            returnValue = ((int)cmd.Parameters["ReturnValue"].Value);
                        }
    
    
                    }
                    catch (System.Exception)
                    {
                        throw;
                    }
                    finally
                    {
                        conn.Close();
                    }
    
                    return returnValue;
                }
    
            }

引用返信 削除キー/
■33024 / inTopicNo.6)  Re[4]: C#からストアドの実行
□投稿者/ 魔界の仮面弁士 大御所(977回)-(2015/07/02(Thu) 19:18:01)
  • アイコンNo33022に返信(みさんの記事)
    > cmd.Parameters.Add(new SqlParameter("@P1", SqlDbType.VarChar));
    それでも大丈夫だとは思いますが、元の定義にあわせて
     new SqlParameter("@P1", SqlDbType.VarChar, 10)
    とした方が、より良いかと思います。


    また、CHAR/VARCHAR/NCHAR/NVARCHAR 指定時は、
    データの特製に併せて、DbType プロパティとして
     AnsiString
     String
     AnsiStringFixedLength
     StringFixedLength
    を使い分けた方が良い場合があります。
    (今回は無指定で OK)


    > catch (System.Exception)
    > {
    > throw;
    > }
    これだと catch する意味が無い様な気も。
引用返信 削除キー/
■33030 / inTopicNo.7)  Re[5]: C#からストアドの実行
□投稿者/ み 一般人(5回)-(2015/07/02(Thu) 20:49:16)
  • アイコン魔界の仮面弁士さん 返信ありがとうございます。
    指摘部分了解しました。

    > また、CHAR/VARCHAR/NCHAR/NVARCHAR 指定時は、
    > データの特製に併せて、DbType プロパティとして
    >  AnsiString
    >  String
    >  AnsiStringFixedLength
    >  StringFixedLength
    > を使い分けた方が良い場合があります。
    > (今回は無指定で OK)

    すみません。この部分ですがどのように実装するのでしょうか

引用返信 削除キー/
■33031 / inTopicNo.8)  Re[6]: C#からストアドの実行
□投稿者/ 魔界の仮面弁士 大御所(979回)-(2015/07/02(Thu) 22:53:36)
  • アイコン
    No33030に返信(みさんの記事)
    >>データの特製に併せて、DbType プロパティとして
    
    特製→特性 m(_ _)m
    
    
    > すみません。この部分ですがどのように実装するのでしょうか
    
    DbType は、SqlParameter のプロパティです。ですから、
    
    cmd.Parameters.Add(new SqlParameter("@P0", SqlDbType.Char, 10) { DbType = DbType.AnsiStringFixedLength });
    
    のように指定するか、もしくは Parameters.Add した後で
    
    cmd.Parameters["@P0"].DbType = DbType.AnsiStringFixedLength;
    
    のように指定すれば OK です。
    
    
    >>また、CHAR/VARCHAR/NCHAR/NVARCHAR 指定時は、
    
    たとえば CHAR(10) 型の列に "ABC" というデータを格納する場合、
    実際には "ABC       " のように 10 桁分の末尾空白が補完されます。
    
    10桁というのが文字数なら、DbType.String/StringFixedLength
    10桁というのがバイト数なら DbType.AnsiString/AnsiStringFixedLength です。
    
    〜FixedLength の方は文字通りの固定長であり、通常は
    CHAR / NCHAR 型に対して、「Size プロパティ」と共に指定します。
    
    というのも、データベースによっては、この末尾空白部分の扱いが異なり、
     WHERE CharFieldName = 'ABC      '
    ではマッチしても、
     WHERE CharFieldName = 'ABC'
    ではマッチしない場合があるからです。(逆に、同一視する環境もあります)
    
    CHAR 型や NCHAR で、この末尾空白が重要な意味を持つ場合、
    Size プロパティと合わせて、DbType プロパティを明示し、そこに
    (Ansi)StringFixedLength を指定することになる、というわけです。
    
    一方、(Ansi)String の方は可変長という事で、
    通常は VARCHAR / NVARCHAR 型に対して用います。

引用返信 削除キー/
■33033 / inTopicNo.9)  Re[7]: C#からストアドの実行
□投稿者/ み 一般人(6回)-(2015/07/03(Fri) 02:34:27)
  • アイコン魔界の仮面弁士さん
    貴重な情報ありがとうございました。
    実装の続きがんばります!
解決み!
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -