1

次で終わるストアドプロシージャを呼び出すC#プログラムをリファクタリングしています。

SELECT @ResultCode AS ResultCode

C#コードは次のようになります。

SqlDbCommand.CommandType = System.Data.CommandType.StoredProcedure;
SqlDbCommand.CommandText = "PR_Foo";

SqlDbCommand.Parameters.Clear();
SqlDbCommand.Parameters.Add("@Foo", SqlDbType.Char);  
SqlDbCommand.Parameters["@Foo"].Value = 'Foo';

System.Data.SqlClient.SqlDataAdapter SqlDbAdapter = new System.Data.SqlClient.SqlDataAdapter();
System.Data.DataSet SQLDataSet = new System.Data.DataSet();
SqlDbAdapter.SelectCommand = SqlDbCommand;
SqlDbAdapter.Fill(SQLDataSet);
SQLDataSet.Tables[0].TableName = "PR_Foo";

if (SQLDataSet.Tables.Count != 0) {
       Result = int.Parse(SQLDataSet.Tables[SQLDataSet.Tables.Count - 1].Rows[0][0].ToString());
}

上記のコードを使用すると、 ストアドプロシージャResultによって返される値が正しく入力されます。

より簡単なコードのリファクタリングExecuteScalar

SqlDbCommand.CommandType = System.Data.CommandType.StoredProcedure;
SqlDbCommand.CommandText = "PR_Foo";

SqlDbCommand.Parameters.Clear();
SqlDbCommand.Parameters.Add("@Foo", SqlDbType.Char); 
SqlDbCommand.Parameters["@Foo"].Value = 'Foo';

Result = (int)SqlDbCommand.ExecuteScalar(); 

値は奇妙なことに0に設定されていResultますが、期待される結果はゼロより大きい整数値である必要があります。

この奇妙な行動の原因が何であるか知っていますか?

ノート:

ストアドプロシージャにはいくつかのifブロックがあり、特定のチェックの場合はゼロ未満の結果値を返します。これらのケースは、ExecuteScalar()によって正しく処理されます。

この問題は、ストアドプロシージャが正しく機能し、さまざまな更新のトランザクションをコミットしてResult、最後に値を返す場合に発生します。

4

4 に答える 4

4

複数のテーブルが返された場合、2 つのコードは同じことをしていません。元のコードは最後のテーブルの最初の行の最初のフィールドを取得しますが、実行スカラーは最初のテーブルの最初の行の最初のフィールドを取得します。これはあなたの問題がある場所でしょうか?

于 2011-08-09T14:06:44.833 に答える
4

私もこの問題に遭遇しました。私の意見では、それは非常に関連性があります。そこで、ここに正しいコードのサンプルを示すことにしました。

    SqlCommand cmd2 = new SqlCommand();
    cmd2.Connection = conn;
    cmd2.CommandType = System.Data.CommandType.StoredProcedure;
    cmd2.CommandText = "dbo.Number_Of_Correct";

    SqlParameter sp0 = new SqlParameter("@Return_Value", System.Data.SqlDbType.SmallInt);
    sp0.Direction = System.Data.ParameterDirection.ReturnValue;
    SqlParameter sp1 = new SqlParameter("@QuestionID", System.Data.SqlDbType.SmallInt);

    cmd2.Parameters.Add(sp0);
    cmd2.Parameters.Add(sp1);

    sp1.Value = 3;

    cmd2.ExecuteScalar();     // int Result = (int)cmd2.ExecuteScalar();  trowns System.NullReferenceException
    MessageBox.Show(sp0.Value.ToString());
于 2012-10-31T12:06:52.930 に答える
2

複数の潜在的な結果セットがあり、あいまいさの可能性がある場合は、ストアド プロシージャを変更して、@ResultCode で選択する代わりに出力パラメーターを使用することを検討してください。

于 2011-08-09T14:24:55.370 に答える
2

あなたが望むのは、最後の結果セットの最初の行の最初のです。残念ながら、プロシージャに複数の select ステートメントがあり、それによって複数の結果セットが生成される場合、ExecuteScalarは最初の結果セット最初の行最初の列のみを取得します。

C# コードの最初のブロックは、プロシージャの最後のselect ステートメントに(正しく) 関連付けられるデータセットの最後のテーブルをチェックします。

于 2011-08-09T14:05:25.413 に答える