c#调用带out类型参数的存储过程拿不到返回值的解决办法
2016-05-31 16:55
706 查看
很平常的一个用法,没遇到过的人不会来看这篇文章,但我遇到了,搜索了,了解了,所以写下了。
首先,带out参数类型存储过程我们写成这样
create procedure winne_Get_ProductsGuiGeFenYe
@pageSize int,
@pageNum int,
@total int output
as
select top (@pageSize) * from [productsGuiGe] where RowID not in(select top ((@pageNum-1)*@pageSize) rowID from dbo.ProductsGuiGe order by RowID) order by RowID;
set @total=(select count(1) from ProductsGuiGe);
这是一个典型的小分页的存储过程,针对这特定的表。代码很简单不用多解释,第一句就是取得记录,第二句就是返回记录总数,是对一个out型参数复制
再来看c#的调用,因为要获取到数据和总条数两个,所以不能用SqlCommand.ExcuteNonQuery来执行这个procedure,我们选择使用SqlCommand.ExcuteReader()来调用,那么问题来了,如果你遇到过:那就是,取得到记录集,就是out参数的@total返回值一直的空的null,就是这个现象。然后在数据库管理界面去执行你的存储过程又能够取到,因此我们确保我们的存储过程是没有问题的。
先看c#代码
--------------------------------------------------调用代码-------------------------------------------------------
以上代码是能够正确拿到想要的值的,对照到代码,我们来总结一下重点地方:
1.首先,要用EcuteReader的话,必须注意,SqlConnection类型的变量不能在using里面使用,如代码段中所示 SqlConnection sqlcon = new SqlConnection(conString);因为返回值sqldatareader在读取的时候是延迟分配,用的时候才会来查询数据库,需要用到这个连接的,放using里面会被方法体出来的时候就被释放掉。
2.上面一点保证了能够正常通过SqlDataReader拿到返回的记录
3.接下来就是out类型参数,一定要等到ExcuteReader方法返回的SqlDataReader关闭掉以后,参会填充值,所以位置很重要,要放在
首先,带out参数类型存储过程我们写成这样
create procedure winne_Get_ProductsGuiGeFenYe
@pageSize int,
@pageNum int,
@total int output
as
select top (@pageSize) * from [productsGuiGe] where RowID not in(select top ((@pageNum-1)*@pageSize) rowID from dbo.ProductsGuiGe order by RowID) order by RowID;
set @total=(select count(1) from ProductsGuiGe);
</pre><p></p><pre>
这是一个典型的小分页的存储过程,针对这特定的表。代码很简单不用多解释,第一句就是取得记录,第二句就是返回记录总数,是对一个out型参数复制
再来看c#的调用,因为要获取到数据和总条数两个,所以不能用SqlCommand.ExcuteNonQuery来执行这个procedure,我们选择使用SqlCommand.ExcuteReader()来调用,那么问题来了,如果你遇到过:那就是,取得到记录集,就是out参数的@total返回值一直的空的null,就是这个现象。然后在数据库管理界面去执行你的存储过程又能够取到,因此我们确保我们的存储过程是没有问题的。
先看c#代码
public static SqlDataReader EcuteReader(string sql, CommandType ctType, SqlParameter[] paras) { SqlConnection sqlcon = new SqlConnection(conString); sqlcon.Open(); using (SqlCommand scmd = new SqlCommand(sql, sqlcon)) { scmd.CommandType = ctType; if (paras.Length > 0) { scmd.Parameters.AddRange(paras); } return scmd.ExecuteReader(); } }
--------------------------------------------------调用代码-------------------------------------------------------
public SqlDataReader GetProductsTypesList(string sql,CommandType ctType,SqlParameter[] paras) { return SqlHelper.EcuteReader(sql, ctType, paras); }--------------------------------------------------使用的代码---------------------------------------------------
public List<ProductsType> GetProductsTypesList(out int total,int pageSize,int pageNum) { ProductsDal pd = new ProductsDal(); SqlParameter[] sp = new SqlParameter[3]; sp[0]=new SqlParameter("@pageSize",SqlDbType.Int); sp[0].Value = pageSize; sp[1] = new SqlParameter("@pageNum", SqlDbType.Int); sp[1].Value = pageNum; sp[2] = new SqlParameter("@total", SqlDbType.Int); sp[2].Direction=ParameterDirection.Output; SqlDataReader sqldr = pd.GetProductsTypesList("winne_Get_ProductsGuiGeFenYe", CommandType.StoredProcedure, sp); List<ProductsType> ProductsTypeList = new List<ProductsType>(); while (sqldr.Read()) { ProductsType pt = new ProductsType(); pt.RowId = int.Parse(sqldr["RowID"].ToString()); pt.FatherName = sqldr["FatherName"].ToString(); pt.TypeDanwei = sqldr["cp_danwei"].ToString(); pt.TypeName = sqldr["GuiGeName"].ToString(); pt.TypeID = sqldr["GuiGeID"].ToString(); pt.Statue = sqldr["shenchan_status"].ToString(); ProductsTypeList.Add(pt); } sqldr.Close(); sqldr.Dispose(); total = int.Parse(sp[2].Value.ToString());//位置 return ProductsTypeList; }
以上代码是能够正确拿到想要的值的,对照到代码,我们来总结一下重点地方:
1.首先,要用EcuteReader的话,必须注意,SqlConnection类型的变量不能在using里面使用,如代码段中所示 SqlConnection sqlcon = new SqlConnection(conString);因为返回值sqldatareader在读取的时候是延迟分配,用的时候才会来查询数据库,需要用到这个连接的,放using里面会被方法体出来的时候就被释放掉。
2.上面一点保证了能够正常通过SqlDataReader拿到返回的记录
3.接下来就是out类型参数,一定要等到ExcuteReader方法返回的SqlDataReader关闭掉以后,参会填充值,所以位置很重要,要放在
sqldr.Close(); sqldr.Dispose(); total = int.Parse(sp[2].Value.ToString());//位置
这样,就能够正常拿到了
3.可能有朋友觉得是不是存储过程里面的两句话的顺序导致的,把out参数赋值放在前面,是不是就可以把接受值放前面了,其实不然,我尝试过这样,答案是否定的,这是ado.net的内部机制,要求程序是这样的,所以,我们只能按照这个顺序来做
</pre><pre code_snippet_id="1702983" snippet_file_name="blog_20160531_9_4837132" name="code" class="csharp">以上代码正常取得,如果我的总结有错误的地方,希望看到的你别一笑了之,这是重在分享和传递,谢谢。
相关文章推荐
- MySQL存储过程
- c#调用COM组件
- ASP程序与SQL存储过程结合使用详解
- C#实现把指定数据写入串口
- C#动态创建button的方法
- C#中抽象方法与虚拟方法的区别
- c#中虚函数的相关使用方法
- C#实现给图片加水印的方法
- C#使用加边法计算行列式的值
- C#实现多线程的同步方法实例分析
- C#中尾递归的使用、优化及编译器优化
- C#中的delegate委托类型基本学习教程
- C#实现子窗体与父窗体通信方法实例总结
- C#通用邮件发送类分享
- 举例讲解C#中自动实现的属性
- C#中this的用法集锦
- C#数据结构之顺序表(SeqList)实例详解
- C#.NET获取拨号连接的宽带连接方法
- C#异步绑定数据实现方法
- C#实现AddRange为数组添加多个元素的方法