两种不同的存储过程调用方法

为了突出新方法的优点,首先介绍一下在.NET中调用存储过程的“官方”方法。另外,本文的所有示例程序均工作于SqlServer数据库上,其它情况类似,以后不再一一说明。本文所有例子均采用C#语言。


  

要在应用程序中访问数据库,一般性的步骤是:首先声明一个数据库连接SqlConnection,然后声明一个数据库命令SqlCommand,用来执行 SQL语句和存储过程。有了这两个对象后,就可以根据自己的需要采用不同的执行方式达到目的。需要补充的是,不要忘记在页面上添加如下的引用语句: using System.Data.SqlClient。


  就执行存储过程来说,如果执行的是第一类存储过程,那么就要用一个 DataAdapter将结果填充到一个DataSet中,然后就可以使用数据网格控件将结果呈现在页面上了;如果执行的是第二和第三种存储过程,则不需要此过程,只需要根据特定的返回判定操作是否成功完成即可。


(1)执行一个没有参数的存储过程的代码如下:


SqlConnection conn=new SqlConnection(“connectionString”);

SqlDataAdapter da = new SqlDataAdapter();

da.SelectCommand = new SqlCommand();

da.SelectCommand.Connection = conn;

da.SelectCommand.CommandText = "NameOfProcedure";

da.SelectCommand.CommandType = CommandType.StoredProcedure;

  然后只要选择适当的方式执行此处过程,用于不同的目的即可。


  (2)执行一个有参数的存储过程的代码如下(我们可以将调用存储过程的函数声明为ExeProcedure(string inputdate)):


SqlConnection conn=new SqlConnection(“connectionString”);

SqlDataAdapter da = new SqlDataAdapter();

da.SelectCommand = new SqlCommand();

da.SelectCommand.Connection = conn;

da.SelectCommand.CommandText = "NameOfProcedure";

da.SelectCommand.CommandType = CommandType.StoredProcedure;

(以上代码相同,以下为要添加的代码)

param = new SqlParameter("@ParameterName", SqlDbType.DateTime);

param.Direction = ParameterDirection.Input;

param.Value = Convert.ToDateTime(inputdate);

da.SelectCommand.Parameters.Add(param);

  这样就添加了一个输入参数。若需要添加输出参数:


param = new SqlParameter("@ParameterName", SqlDbType.DateTime);

param.Direction = ParameterDirection.Output;

param.Value = Convert.ToDateTime(inputdate);

da.SelectCommand.Parameters.Add(param);

  若要获得参储过程的返回值:


param = new SqlParameter("@ParameterName", SqlDbType.DateTime);

param.Direction = ParameterDirection.ReturnValue;

param.Value = Convert.ToDateTime(inputdate);

da.SelectCommand.Parameters.Add(param);

  从上面的代码我们可以看出,当存储过程比较多或者存储过程的参数比较多时,这种方法会大大影响开发的速度;另外一方面,如果项目比较大,那么这些用于数据库逻辑的函数在以后的维护中也是一个很大的负担。那么,有没有一种改进的方法可以解决这个问题呢?想到在执行没有参数的存储过程时只需要传入一个存储过程的名字就可以调用相应的存储过程,而且在SqlServer数据库中我们可以直接在查询分析器中敲入“存储过程名(参数列表)”样的字符串就可以执行存储过程,那么,是否可以把这种思想应用到应用程序中呢?


  于是在编译器中键入相应代码。这些代码是在调用不带参数的存储过程的代码的基础上改的。具体代码如下:


SqlConnection conn=new SqlConnection(“connectionString”);

SqlDataAdapter da = new SqlDataAdapter();

da.SelectCommand = new SqlCommand();

da.SelectCommand.Connection = conn;

da.SelectCommand.CommandText = "NameOfProcedure(’para1’,’para2’,para3)";

da.SelectCommand.CommandType = CommandType.StoredProcedure;

  为了使代码更具有代表性,要调用的存储过程的第一个和第二个参数都为字符串类型,第三个参数为整型。执行以后发现,完全可以达到预期的效果!


  两种调用方法的比较

  

  通过比较我们可以看到,第二种方法具有一个很明显的优点,那就是可以提高开发速度,节省开发时间,而且代码容易维护,在一定程度上也减少了系统大小。但是,由于对存储过程参数的处理比较笼统,如果要获取输出参数或者得到存储过程的返回值,这种方法就不能满足需要了。虽然如此,但是,这种方法毕竟可以让开发人员少些很大一部分的代码。如果不需要获取输出参数和返回值,那么几乎可以做到“一劳永逸”。因此在实际的程序开发中,这种方法还是具有一定的实用价值的。

有参数型的调用方法:

//===============================================================================

// This file is based on the Microsoft Data Access Application Block for .NET

// For more information please go to

// ​​http://msdn.microsoft.com/library/en-us/dnbda/html/daab-rm.asp​

//===============================================================================

using System;

using System.Configuration;

using System.Data;

using System.Data.SqlClient;

using System.Collections;

namespace DataBusiness

{

/// <summary>

/// DataExecute 的摘要说明。

/// </summary>

public class DataExecute

{

  //Database connection strings

        public static readonly string CONN_STRING = System.Configuration.ConfigurationManager.ConnectionStrings["HomeTeachingString"].ConnectionString;

 

  // Hashtable to store cached parameters

  private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

  /// <summary>

  /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <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>

  public static int ExecuteNonQuery(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

   SqlCommand cmd = new SqlCommand();

   using (SqlConnection conn = new SqlConnection(connString))

   {

    PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

    int val = cmd.ExecuteNonQuery();

    //清除cmd的参数

    cmd.Parameters.Clear();

                conn.Close();

    return val;

   }

  }

  /// <summary>

  /// Execute a SqlCommand (that returns no resultset) against an existing database connection

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <param name="conn">an existing database connection</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>

  public static int ExecuteNonQuery(SqlConnection conn, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

   SqlCommand cmd = new SqlCommand();

   PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

   int val = cmd.ExecuteNonQuery();

   cmd.Parameters.Clear();

            conn.Close();

   return val;

  }

  /// <summary>

  /// Execute a SqlCommand (that returns no resultset) using an existing SQL Transaction

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <param name="trans">an existing sql transaction</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>

  public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

   SqlCommand cmd = new SqlCommand();

   PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, cmdParms);

   int val = cmd.ExecuteNonQuery();

   cmd.Parameters.Clear();

   return val;

  }

  /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in

  /// the connection string.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders");

  /// </remarks>

  /// <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>

  /// <returns>a SqlDataReader containing the resultset generated by the command</returns>

  public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText)

  {

   //pass through the call providing null for the set of SqlParameters

   return ExecuteReader(connectionString, commandType, commandText, (SqlParameter[])null);

  }

  /// <summary>

  /// Execute a SqlCommand that returns a resultset against the database specified in the connection string

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <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>A SqlDataReader containing the results</returns>

  public static SqlDataReader ExecuteReader(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

   SqlCommand cmd = new SqlCommand();

   SqlConnection conn = new SqlConnection(connString);

   try

   {

    PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

    SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

    cmd.Parameters.Clear();

    return rdr;

   }

   catch

   {

    conn.Close();

    throw;

   }

  }

 

  /// <summary>

  /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in

  /// the connection string.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders");

  /// </remarks>

  /// <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>

  /// <returns>a dataset containing the resultset generated by the command</returns>

  public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText)

  {

   return ExecuteDataset(connectionString, commandType, commandText, (SqlParameter[])null);

  }

  /// <summary>

  /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <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>a dataset containing the resultset generated by the command</returns>

  public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)

  {

   using (SqlConnection cn = new SqlConnection(connectionString))

   {

    cn.Open();

    //调用重载方法

    return ExecuteDataset(cn, commandType, commandText, commandParameters);

   }

  }

  /// <summary>

  /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders");

  /// </remarks>

  /// <param name="connection">a valid SqlConnection</param>

  /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>

  /// <param name="commandText">the stored procedure name or T-SQL command</param>

  /// <returns>a dataset containing the resultset generated by the command</returns>

  public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText)

  {

   return ExecuteDataset(connection, commandType, commandText, (SqlParameter[])null);

  }

 

  /// <summary>

  /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <param name="connection">a valid 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>a dataset containing the resultset generated by the command</returns>

  public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)

  {

   //创建一个SqlCommand对象,并对其进行初始化

   SqlCommand cmd = new SqlCommand();

   PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);

  

   //创建SqlDataAdapter对象以及DataSet

   SqlDataAdapter da = new SqlDataAdapter(cmd);

   DataSet ds = new DataSet();

   //填充ds

   da.Fill(ds);

  

   // 清除cmd的参数集合

   cmd.Parameters.Clear();

  

   //返回ds

   return ds;     

  }

 

  /// <summary>

  /// Execute a SqlCommand that returns the first column of the first record against the database specified in the connection string

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <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 object that should be converted to the expected type using Convert.To{Type}</returns>

  public static object ExecuteScalar(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

   SqlCommand cmd = new SqlCommand();

   using (SqlConnection conn = new SqlConnection(connString))

   {

    PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

    object val = cmd.ExecuteScalar();

    cmd.Parameters.Clear();

    return val;

   }

  }

  /// <summary>

  /// Execute a SqlCommand that returns the first column of the first record against an existing database connection

  /// using the provided parameters.

  /// </summary>

  /// <remarks>

  /// e.g.: 

  ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));

  /// </remarks>

  /// <param name="conn">an existing database connection</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 object that should be converted to the expected type using Convert.To{Type}</returns>

  public static object ExecuteScalar(SqlConnection conn, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)

  {

  

   SqlCommand cmd = new SqlCommand();

   PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

   object val = cmd.ExecuteScalar();

   cmd.Parameters.Clear();

   return val;

  }

  /// <summary>

  /// add parameter array to the cache

  /// </summary>

  /// <param name="cacheKey">Key to the parameter cache</param>

  /// <param name="cmdParms">an array of SqlParamters to be cached</param>

  public static void CacheParameters(string cacheKey, params SqlParameter[] cmdParms)

  {

   parmCache[cacheKey] = cmdParms;

  }

  /// <summary>

  /// Retrieve cached parameters

  /// </summary>

  /// <param name="cacheKey">key used to lookup parameters</param>

  /// <returns>Cached SqlParamters array</returns>

  public static SqlParameter[] GetCachedParameters(string cacheKey)

  {

   SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];

  

   if (cachedParms == null)

    return null;

  

   SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];

   for (int i = 0, j = cachedParms.Length; i < j; i++)

    clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

   return clonedParms;

  }

  /// <summary>

  /// Prepare a command for execution

  /// </summary>

  /// <param name="cmd">SqlCommand object</param>

  /// <param name="conn">SqlConnection object</param>

  /// <param name="trans">SqlTransaction object</param>

  /// <param name="cmdType">Cmd type e.g. stored procedure or text</param>

  /// <param name="cmdText">Command text, e.g. Select * from Products</param>

  /// <param name="cmdParms">SqlParameters to use in the command</param>

  private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)

  {

   //判断连接的状态。如果是关闭状态,则打开

   if (conn.State != ConnectionState.Open)

    conn.Open();

   //cmd属性赋值

   cmd.Connection = conn;

   cmd.CommandText = cmdText;

   //是否需要用到事务处理

   if (trans != null)

    cmd.Transaction = trans;

   

   cmd.CommandType = cmdType;

   //添加cmd需要的存储过程参数

   if (cmdParms != null)

   {

    foreach (SqlParameter parm in cmdParms)

     cmd.Parameters.Add(parm);

   }

  }

}

}

            SqlParameter[] para = {

           new SqlParameter("@studentID", studentID),

           new SqlParameter("@require_course", require_course),

           new SqlParameter("@require_sex", require_sex),

           new SqlParameter("@require_money", require_money),

           new SqlParameter("@require_address",require_address ),

           new SqlParameter("@require_info", require_info),

           new SqlParameter("@input_date", input_date),

   };

            DataExecute.ExecuteNonQuery(DataExecute.CONN_STRING, CommandType.StoredProcedure,

                "AddRequire", para);

 

 

 

if exists(select * from sys.objects where type = 'p' and name = '<porcedure name >' )

print 'exists in db'

else

print 'not exists'