c#调用带out类型参数的存储过程拿不到返回值的解决办法

原创 2016年05月31日 16:55:18

      很平常的一个用法,没遇到过的人不会来看这篇文章,但我遇到了,搜索了,了解了,所以写下了。


      首先,带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">以上代码正常取得,如果我的总结有错误的地方,希望看到的你别一笑了之,这是重在分享和传递,谢谢。



C# SQL带传入、输出参数及返回值的存储过程

/// /// 带传入参数的存储过程 /// /// /// protected void Button3_Cl...
  • o527883184
  • o527883184
  • 2016年04月17日 22:48
  • 2493

C# 关于out关键字的用法(一个方法返回多个值的问题)

通常一个方法只能返回一个值,但是如果在某些时候,我们想要返回多个值,例如某个方法将一个浮点数分割成一个整数和一个小数返回去。这个时候我们就要用到out关键字。 如果用ref也可以解决,但是用ref需...
  • shoneworn
  • shoneworn
  • 2015年12月26日 15:06
  • 1336

C#调用存储过程带输出参数或返回值

CREATE PROCEDURE [dbo].[GetNameById] @studentid varchar(8), @studentname nvarchar(50) OUTPUT AS BE...
  • smartsmile2012
  • smartsmile2012
  • 2014年05月26日 14:02
  • 18848

c#中使用call调用oracle存储过程并获取out参数值

1.创建测试存储过程:SQL> create or replace procedureproc_test(p1 INvarchar2,p2 OUT varchar2) is 2  begin 3   ...
  • zhpsam109
  • zhpsam109
  • 2005年12月20日 11:18
  • 6425

C#返回多个参数 ref及out

out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。例如...
  • mihenyinghua
  • mihenyinghua
  • 2011年11月08日 21:30
  • 7182

存储过程+调用存储过程+无/带参的存储过程+in参数+out参数+int out参数+为参数设置默认值

存储过程 1存储过程是一组为了完成特定功能的SQL语句集 2存储过程编译后存储在数据库中 3执行存储过程比执行存储过程封装的SQl语句集更有效率 4不能指定declare关键字 5: OUT...
  • zhou920786312
  • zhou920786312
  • 2017年05月23日 23:39
  • 1936

C#调用存储过程带输出参数或返回值

CREATE PROCEDURE [dbo].[GetNameById] @studentid varchar(8), @studentname nvarchar(50) OUTPUT AS BE...
  • smartsmile2012
  • smartsmile2012
  • 2014年05月26日 14:02
  • 18848

C#获取存储过程返回值和输出参数值的方法

这篇文章主要介绍了C#获取存储过程返回值和输出参数值的方法,有需要的朋友可以参考一下 1.获取Return返回值 复制代码代码如下: //存储过程 ...
  • ycl295644
  • ycl295644
  • 2015年05月21日 08:57
  • 2355

JAVA程序调用MYSQL带有OUTPUT参数的存储过程

JAVA程序调用MYSQL带有OUTPUT参数的存储过程实现思路 (1) 给存储过程参数列表中定义带OUTPUT 输出参数 ,关键字(参数名称 ,数据类型,OUTPUT)    例如 :    ps_...
  • JenMinZhang
  • JenMinZhang
  • 2013年07月29日 17:38
  • 7977

MyBatis调用带有返回结果、output参数的存储过程上与ibatis的区别

用过mybatis的应该都知道它是ibatis被Google收购后重新命名的一个工程,因此也做了大量升级。本文就来介绍下两者在调用存储过程上的一点区别,ibatis有一个专门的标签,在mybatis里...
  • hj7jay
  • hj7jay
  • 2017年07月19日 09:41
  • 943
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c#调用带out类型参数的存储过程拿不到返回值的解决办法
举报原因:
原因补充:

(最多只允许输入30个字)