关于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 对象,还要注意存储过程参数名称等问题。下面是第一种方法调用例子:

代码
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 关闭之前,将无法访问返回值和输出参数。下面是个例子:

 

代码
 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();
   }
 }

 

 

posted @ 2010-11-25 16:16  闭着眼睛想  阅读(4257)  评论(1编辑  收藏  举报