1

Visual Studio 2010 を使用して、データベースを使用して ac# Web アプリケーションを作成しています。私の目標は、テーブルからエントリを選択して返すストアド プロシージャを実行する ac# クラスを default.aspx で呼び出すことです。コードは次のとおりです。

'The stored procedure.  I want it to send back the name it gets from doing
'the query to the c# class.
ALTER PROCEDURE getName (@id int)
AS
BEGIN
SET NOCOUNT ON;

--   
SELECT name FROM tableA where id = @id;

END 
Return
//Here's the c# class I'm using.
public class student
{
    public string name;
    public int id;

    public student()
    { }

    public String doQuery(int id)
    {
        SqlConnection conn = null;

        try
        {
             conn = new SqlConnection("Server =(local); Database = Database1.mdf;
   Integrated Security = SSPI");
            conn.Open();
            SqlCommand cmd = new SqlCommand("getName", conn);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter param = new SqlParameter("@id", SqlDbType.Int);
            param.Direction = ParameterDirection.Input;
            param.Value = id;
            cmd.Parameters.Add(param);
            //This is some code from when I tryed return value
            //SqlParameter reVal = cmd.Parameters.Add("@name", SqlDbType.VarChar);
            //reVal.Direction = ParameterDirection.ReturnValue;

            //before using ExecuteScalar I tried ExcuteNonQuery with the commented    
            //out code
            name = (string)cmd.ExecuteScalar();

            //name = (String)cmd.Parameters["@name"].Value;

            conn.Close();
        }

        catch(Exception)
        {}
        return name;
    }
}

プログラムを実行してもエラーは返されず、単に名前に値が設定されません。SQLプロシージャで選択された名前をc#クラスの名前変数に取得するために何が欠けていますか。私の問題を明確に伝えていることを願っています。

edit1:エラーが発生したことを確認するために何を使用するかを決定していなかったので、キャッチ原因に何も入れませんでした。試行に失敗したときに name = "error" にするように変更しました。それが私が得るものであり、それが私が得るものです。また、SQLサーバー管理で「exec getName 5、otherstuff」を実行してみました。exec getName を実行するときに 2 番目のパラメーターとして何を使用するかについては少しわかりません。コマンドが正常に実行されたと表示されますが、id 5 の名前は表示されません。

4

2 に答える 2

2

SQLステートメントにはasync/awaitパターンを使用することをお勧めします。幸い、多くのリファクタリングは必要ありません。

これがあなたのために働くかどうか見てください:

public async Task<string> QueryGetNameAsync(int id)
{
  using (var dbConn = new SqlConnection("..."))
  using (var command = new SqlCommand("getName", dbConn))
  {
    try
    {
      command.CommandType = CommandType.StoredProcedure;
      command.Parameters.AddWithValue("@id", id);

      await dbConn.OpenAsync();

      var result = await command.ExecuteScalarAsync();
      dbConn.Close();

      var name = result as string;          
      return name;
    }
    catch (Exception ex)
    {
      // Handle exception here.
    }
  }
}

あなたはそれを次のようなもので呼ぶでしょう:

private async void DoLookup_Clicked(object sender, EventArgs e)
{
   var id = int.Parse(idText.Text);
   var name = await QueryGetNameAsync(id);
}

または、 SQLOUTPUTでパラメータを使用することもできますが、ストアドプロシージャを次のように調整する必要があります。

ALTER PROCEDURE getName
(
  @id int, 
  @name varchar(100) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON;

SELECT @name = name FROM tableA where id = @id;

END 

その場合、C#関数は次のようになります。

public async Task<string> QueryGetNameAsync(int id)
{
  using (var dbConn = new SqlConnection("..."))
  using (var command = new SqlCommand("getName", dbConn))
  {
    try
    {
      command.CommandType = CommandType.StoredProcedure;
      command.Parameters.AddWithValue("@id", id);
      command.Parameters.Add("@name", SqlDbType.VarChar, 100);
      command.Parameters["@name"].Direction = ParameterDirection.Output;

      await dbConn.OpenAsync();
      await command.ExecuteNonQueryAsync();
      dbConn.Close();

      var name = command.Parameters["@name"].Value as string;          
      return name;
    }
    catch (Exception ex)
    {
      // Handle exception here.
    }
  }
}
于 2013-01-14T00:13:39.673 に答える
2

問題は接続文字列にあります。変な命名規則がない限り、データベース自体の名前ではなく、データベース ファイル名を指定しています。

接続文字列のこの部分を に変更してみてDatabase = Database1.mdf;くださいDatabase = Database1;

接続文字列で有効なものと無効なものについて混乱している場合は、正しいプロパティを設定した後に適切な接続文字列を作成するSqlConnectionStringBuilderをいつでも使用できます。

SqlConnection.ConnectionStringドキュメントで指定されているプロパティのリストを、例を含むリファレンスとして使用することもできます。

最後に、次のベスト プラクティスを強くお勧めします。

1) 接続とコマンドでブロックを使用して、それらが適切に閉じられ、破棄されていることを確認します。

2) ExecuteScalar の結果が DBNull.Value として返される場合は、名前を直接割り当てないでください。

3) 例外を無視する理由をコードで文書化していない限り、決して例外を無視しないでください。

上記のすべての推奨事項を簡単に書き直したものを次に示します。

        try
        {
            using (var conn = new SqlConnection("Server =(local); Database = Database1; Integrated Security = SSPI"))
            {
                conn.Open();
                using (var cmd = new SqlCommand("getName", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    var param = new SqlParameter("@id", SqlDbType.Int);
                    param.Direction = ParameterDirection.Input;
                    param.Value = id;
                    cmd.Parameters.Add(param);

                    var oResult = cmd.ExecuteScalar();
                    if ((oResult != null) && (oResult != DBNull.Value))
                    {
                        name = (string)oResult;
                    }
                }
                conn.Close();
            }
        }

        catch (Exception)
        { 
            //  Do something with the exception here, don't just ignore it
        }
于 2013-01-14T01:30:24.997 に答える