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(); 

Result值奇怪地设置为 0,而预期结果应该是大于零的整数值。

你知道这种奇怪行为的原因是什么吗?

笔记:

存储过程有几个 if 块,在特定检查的情况下返回低于零的结果值;这些情况由 ExecuteScalar() 正确处理。

当存储过程正确完成其工作、提交各种更新的事务并Result在最后返回值时,就会出现问题。

4

4 回答 4

4

如果返回多个表,您的两段代码不会做同样的事情。您的原始代码采用最后一个表的第一行的第一个字段,而执行标量将采用第一个表的第一行的第一个字段。这可能是您的问题所在吗?

于 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

您似乎想要的是最后一个 result-set第一行的第一。不幸的是,如果您的过程中有多个 select 语句,从而生成多个结果集,则ExecuteScalar只会获取第一个结果集第一行的第一

您的第一个 C# 代码块检查数据集中的最后一个表,该表将(正确地)与过程中的最后一个select 语句相关联。

于 2011-08-09T14:05:25.413 回答
2

如果您有多个潜在的结果集,并且可能存在歧义,您可以考虑更改存储过程以使用输出参数而不是 @ResultCode 上的选择。

于 2011-08-09T14:24:55.370 回答