关于sqlhelper调用存储过程获取参数返回值和输出参数的问题

SqlHelper类调用存储过程的方法有下面类似的两种类型:

/// <param name="connectionString">A valid connection string for a SqlConnection</param>
/// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">The stored procedure name or T-SQL command</param>
/// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
/// <returns>An int representing the number of rows affected by the command</returns>
1、public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)

/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
</remarks>
2、public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)

第一种方法调用存储过程是可以获得存储过程返回值的

第二种方法调用存储过程是获取不了返回值和输出参数的

原因:

仔细看的里面的实现将会发现:
它调用了:GetSpParameterSet(connection, spName, false);
接着调用:GetSpParameterSetInternal(clonedConnection, spName, includeReturnValueParameter);
在GetSpParameterSetInternal里面有这样的判断:
string hashKey = connection.ConnectionString + ":" + spName + (includeReturnValueParameter ? ":include ReturnValue Parameter":"");

很显然没有返回值,然后在DiscoverSpParameterSet方法内通过

if (!includeReturnValueParameter) 
{
       cmd.Parameters.RemoveAt(0);//由于自动检测参数时, 会在参数列表的首项加入@Return_Value.如果不需要它时,就要移去
}
消除返回参数。其实由于第二种方法传递的是object类型的数据进去,根本就没有把需要返回参数返回值这种信息传递进去,程序无法知道你是不是需要返回参数的值。而且object类型是值类型,函数内改变它的值也带不回来。

之所以会有第二种调用方法是为了我们能更方便的调用存储过程,不必去关系存储过程参数名是什么,知道它的参数顺序就可以了,它主要是利用SqlCommandBuilder.DeriveParameters(cmd);来获取参数信息的,利用hashtable保存了Parameters。(为什么要用hashtable来保存,不保存应该也可以行的通的,还是从hashtable 里才clone一份Parameters出来用的。用静态的hashtable存储了最近一次调用的SqlParameter ,如果下次还是同一次调用,速度会快一些,不用去SqlCommandBuilder.DeriveParameters了,少连一次数据库)第一种方法显然是要麻烦很多,要创建 SqlParameter 对象,还要注意存储过程参数名称等问题。下面是第一种方法调用例子:

ExpandedBlockStart.gif 代码
public   static   int  InsertBrand(Brand brand)
{
  SqlParameter[] ParamList 
= {   
      SqlHelper.MakeInParam(
" @BrandName " ,SqlDbType.VarChar, 32 ,brand.BrandName),
      SqlHelper.MakeRetParam(
" @Ret " ,SqlDbType.Int, 4 )                              
  };
  SqlConnection connection 
=   new  SqlConnection(DbConn.ConnectString);
  
try
  {
     SqlHelper.ExecuteNonQuery(connection, CommandType.StoredProcedure, 
" SP_Brand_Insert " , ParamList);
     
return  Int32.Parse(ParamList[ 1 ].Value.ToString());
  }
  
catch  (Exception ex)
  {
     
throw   new  Exception(ex.Message, ex);
  }
  
finally
  {
     connection.Close();
     connection.Dispose();
  }
}

 

输出参数的问题:

当 Command 对象用于存储过程时,可以将 Command 对象的 CommandType 属性设置为 StoredProcedure。当 CommandType 为 StoredProcedure 时,可以使用 Command 的 Parameters 属性来访问输入及输出参数和返回值。无论调用哪一个 Execute 方法,都可以访问 Parameters 属性。但是,当调用 ExecuteReader 时,在 DataReader 关闭之前,将无法访问返回值和输出参数。下面是个例子:

 

ExpandedBlockStart.gif 代码
  public   static  List < Clothes >  GetPagesClothes( int  currentPage,  int  pageSize, out   int  rowsCount)
 {
   SqlParameter[] ParamList 
= {   
     SqlHelper.MakeInParam(
" @CurrentPage " ,SqlDbType.Int, 4 ,currentPage),
     SqlHelper.MakeInParam(
" @PageSize " ,SqlDbType.Int, 4 ,pageSize),
     SqlHelper.MakeOutParam(
" @RecordCount " ,SqlDbType.Int, 4 )
    };
   SqlConnection connection 
=   new  SqlConnection(DbConn.ConnectString);
   SqlDataReader dr 
=   null ;
   
try
    {
      dr
= SqlHelper.ExecuteReader(connection, CommandType.StoredProcedure,  " SP_Clothes_GetAll_Page " , ParamList);                
      List
< Clothes >  listClothes  =   new  List < Clothes > ();
      
while  (dr.Read())
      {
        Clothes c 
=   new  Clothes();
        c.ClothesId 
=  Int64.Parse(dr[ " ClothesId " ].ToString());
        c.ClothesName 
=  dr[ " ClothesName " ==   null   ?   null  : dr[ " ClothesName " ].ToString();
        c.ClothesNums 
=  dr[ " ClothesNums " ].ToString();
        
if  (dr[ " ClothesSex " ].ToString()  ==   " " ) c.ClothesSex  =   1 ;
        
if  (dr[ " ClothesSex " ].ToString()  ==   " " ) c.ClothesSex  =   0 ;
        c.CBrand 
=   new  Brand() { BrandId  =   byte .Parse(dr[ " BrandId " ].ToString()), BrandName  =  dr[ " BrandName " ].ToString() };
        c.CStyle 
=   new  Style() { StyleId  =   byte .Parse(dr[ " StyleId " ].ToString()), StyleName  =  dr[ " StyleName " ].ToString() };
        c.CSeason 
=   new  Season() { SeasonId  =   byte .Parse(dr[ " SeasonId " ].ToString()), SeasonName  =  dr[ " SeasonName " ].ToString() };
        c.CPattern 
=   new  Pattern() { PatternId  =   byte .Parse(dr[ " PatternId " ].ToString()), PatternName  =  dr[ " PatternName " ].ToString() };
        c.CClass 
=   new  Class() { ClassId  =   byte .Parse(dr[ " ClassId " ].ToString()), ClassName  =  dr[ " ClassName " ].ToString() };
        c.SmallPic 
=  ( byte [])dr[ " SmallPic " ];
        c.ShowPic 
=  ( byte [])dr[ " ShowPic " ];
        c.Memo 
=  dr[ " Memo " ].ToString();
        listClothes.Add(c);
       }
      dr.Close();
      dr.Dispose();
      rowsCount 
=  Int32.Parse(ParamList[ 2 ].Value.ToString());
      
return  listClothes;
    }
  
catch  (Exception ex)
   {
      
throw   new  Exception(ex.Message, ex);
   }
   
finally
   {
      connection.Close();
      connection.Dispose();
   }
 }

 

 

转载于:https://www.cnblogs.com/love_study/archive/2010/11/25/1887781.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值