我创建了一个类似于这个简化示例的存储过程:
CREATE PROCEDURE dbo.sp_MyStoredProcedure
@Var1 INT OUTPUT,
@Var2 DECIMAL(10,2) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@Var1 = COUNT(*),
@Var2 = SUM(TranAmount)
FROM
MyTable
SELECT * FROM MyTable
END
当我在调用ExecuteReader()
对象的SqlCommand
方法后尝试读取输出变量中的值时,值为空。
string MyConnString = string.Empty;
SqlConnection MyConn = new SqlConnection(MyConnString);
SqlCommand MyCmd = new SqlCommand("sp_MyStoredProcedure", MyConn);
MyCmd.CommandType = CommandType.StoredProcedure;
MyCmd.Parameters.Add(new SqlParameter("@Var1", SqlDbType.Int));
MyCmd.Parameters.Add(new SqlParameter("@Var2", SqlDbType.Decimal);
MyCmd.Parameters[0].Direction = ParameterDirection.Output;
MyCmd.Parameters[1].Direction = ParameterDirection.Output;
SqlDataReader dr = MyCmd.ExecuteReader(CommandBehavior.CloseConnection);
int Var1 = Convert.ToInt32(MyCmd.Parameters[0].Value);
decimal Var1 = Convert.ToDecimal(MyCmd.Parameters[1].Value);
我做错了什么?
答案 0 :(得分:10)
您需要阅读阅读器直到结束,输出参数位于TDS流的末尾,客户端将不会看到它们,直到结果集未被消耗。
如果在读取结果集之前必须有计数和总和,则必须抛弃OUTPUT参数。只需生成一个普通的结果集,其中包含您感兴趣的两个值,然后购买SELECT *结果集。然后使用SqlDataReader.NextResult()读取客户端中的两个结果集。
<强>更新强>
我的意思是设置两个结果:
CREATE PROCEDURE dbo.sp_MyStoredProcedure
AS
BEGIN
SET NOCOUNT ON;
SELECT COUNT(*) as cnt, SUM(TranAmount) as sum_ta
FROM MyTable
SELECT * FROM MyTable
END
和客户:
string MyConnString = string.Empty;
SqlConnection MyConn = new SqlConnection(MyConnString);
SqlCommand MyCmd = new SqlCommand("sp_MyStoredProcedure", MyConn);
MyCmd.CommandType = CommandType.StoredProcedure;
using(SqlDataReader dr = MyCmd.ExecuteReader(CommandBehavior.CloseConnection))
{
while(dr.Read())
{
count = dr["cnt"];
sum = dr["sum_ta"];
}
dr.NextResult();
while(dr.Read())
{
// process MyTable row here
}
}
请注意,如果您的C#代码在使用数据读取器之前不需要输出参数的值,则不需要执行此操作。您可以直接读取SqlDataReader直到结束,然后检查输出参数,它们将被设置。
答案 1 :(得分:1)
正如Remus所说,如果您首先需要它,那么您需要重新查询您的查询方式。为什么不分两个单独的程序?这将是抽象的最佳解决方案。
否则,您可以在同一批次
中执行两个SQL语句SELECT COUNT(*) AS VAR1, SUM(TranAmount) AS VAR2 FROM MyTable
SELECT * FROM MyTable
然后当你调用ExecuteReader
时SqlDataReader dr = MyCmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dr.read())
{
var1 = dr["Var1"];
var2 = dr["Var2"];
}
dr.NextResult();
while (dr.read())
{
// blah blah blah code
}