ExecuteScalar返回0执行存储过程

本文关键字:存储过程 执行 返回 ExecuteScalar | 更新日期: 2023-09-27 18:04:50

我正在重构一个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,而预期的结果应该是一个大于0的整数值。

你知道是什么导致了这种奇怪的行为吗?

注意:

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

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

ExecuteScalar返回0执行存储过程

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

我也遇到过这个问题。在我看来,这是非常相关的。所以我决定在这里给出正确的代码示例。

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

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

您似乎想要的是最后一个结果集第一行第一列。不幸的是,如果在过程中有多个选择语句,从而生成多个结果集,那么ExecuteScalar只会获得第一个结果集第一行第一列

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