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
值时,问题就出现了。
在返回多个表的情况下,您的两段代码不会做相同的事情。您的原始代码采用最后表第一行的第一个字段,而执行标量将采用第一个表第一行的第一个字段。这就是你的问题所在吗?
我也遇到过这个问题。在我看来,这是非常相关的。所以我决定在这里给出正确的代码示例。
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语句关联。