存储过程的输出参数的使用,相信大家早晚多少都(会)用到过。不知用到过朋友,有没有遇到在程序中“咋就”取不到想要的输出值的情况;始终是null值。昨天本人就遇到了,也可能是用的不多,这种情况也是第一次遇到。项目中也不是只有一次用到输出参数,但也没有出现这样情况。跟同事讨论一下也没问出个所以然来,让搞架构师的同事调试一下也没结果。他也一直纳闷,其它地方用的好好的,咋这地方就不行呢!项目中的业务逻辑基础通用代码都是通过模板自动生成的。没办法,只好笨方法了;对比一下能用的地方的代码,一点一点的追根溯源;看看到底区别在哪里。最后锁定在数据访问层用到的系统方法ExecuteReader和ExecuteNonQuery上;也是大概猜的,难道是出在这里吗?为方便读者观察就把最后代码贴出来了。
public int ExecuteSPNonQuery(string procedureName)
{
SqlCommand cmd = new SqlCommand();
this.Connect();
int effectedRows = -1;
cmd.CommandTimeout = this.CommandTimeout;
cmd.CommandText = procedureName;
cmd.Connection = _connection;
if (_transaction != null) cmd.Transaction = _transaction;
cmd.CommandType = CommandType.StoredProcedure;
this.CopyParameters(cmd);
effectedRows = cmd.ExecuteNonQuery();
_parameterCollection = cmd.Parameters;
cmd.Dispose();
if (this.AutoCloseConnection) this.Disconnect();
return effectedRows;
}
public DbDataReader ExecuteSPReader(string procedureName)
{
SqlDataReader reader;
SqlCommand cmd = new SqlCommand();
this.Connect();
cmd.CommandTimeout = this.CommandTimeout;
cmd.CommandText = procedureName;
cmd.Connection = _connection;
if (_transaction != null) cmd.Transaction = _transaction;
cmd.CommandType = CommandType.StoredProcedure;
this.CopyParameters(cmd);
CommandBehavior behavior = CommandBehavior.Default;
if (this.AutoCloseConnection) behavior = behavior | CommandBehavior.CloseConnection;
if (_isSingleRow) behavior = behavior | CommandBehavior.SingleRow;
reader = cmd.ExecuteReader(behavior);
_parameterCollection = cmd.Parameters;
cmd.Dispose();
return reader;
}
基本上一样,除了些不相干代码;问题大概就在那个地方了。此时咋办?打开搜索引擎,输入“Output ExecuteReader “,点击搜索。结果又是一大堆!打开一看热心的网友早把情况贴出来了。通过ExecuteReader(), 要想能取出输出参数值,必须把reader close掉后可以。二话不说试了一下,果不其然;关掉再从cmd.Parameters 中取出对应的输出参数值就可以了。而用ExecuteNonQuery()是不会出现这样问题的。后来和那个搞架构的同事说了,他才恍然大悟。他说遇到过,而且也改了对应模板;只是忘记迁入到我们项目模板中了。晕倒!
引发思考:ParameterDirection枚举里面四个成员的区别(来自微软官方网)http://technet.microsoft.com/zh-cn/magazine/system.data.parameterdirection(VS.90).aspx
Input 参数是输入参数。
Output 参数是输出参数。
InputOutput 参数既能输入,也能输出。
ReturnValue 参数表示诸如存储过程、内置函数或用户定义函数之类的操作的返回值。
注意事项:http://www.cnblogs.com/Dlonghow/archive/2008/11/19/1336406.html
1、.Net中的参数定义为形式参数 而把存储过程的参数定义为实际参数;
2、数据库存储过程的实际参数如果没有默认值则形式参数必须传值给实际参数;
3、但是如果形式参数的类型为ParameterDirection.Output 则传给实际参数的永远是空值;
4、如果形式参数的类型为ParameterDirection.ReturnValue 则形式参数不会传值给实际参数 实际参数必须有默认值 否则代码会报错;
5、如果形式参数类型为ParameterDirection.InputOutput 或者 ParameterDirection.Output 则实际参数必须有output 关键字.
引用他例:http://hi.baidu.com/jeloly/blog/item/05743424d25e653a8744f904.html
ParameterDirection.ReturnValue 和ParameterDirection.OutPut返回值的区别?
Output 参数是输出参数。
ReturnValue 参数表示诸如存储过程、内置函数或用户定义函数之类的操作的返回值。
示例如下:
create proc 名称 @out int out
as
begin
set @out = 100;
return 200;
end
这个out就是output参数
返回的200是returnvalue,
output参数可能有多个,return value只有一个
总结:Output、ReturnValue都可以返回存储过程处理过的值,ReturnValue只能返回一个值,而output可以设置一个或多个返回值,这就是区别。
kevin.chen
2012-02-28