SqlHelper.cs
上传用户:lishan0805
上传日期:2019-12-08
资源大小:12048k
文件大小:82k
源码类别:

OA系统

开发平台:

C#

  1. // =================================================================== 
  2. // 产品(COM.OA.SqlServerDAL)项目
  3. //====================================================================
  4. // wangyp @Copy Right 2006-2008
  5. // 文件:SqlHelper.cs
  6. // 项目名称:工程项目管理 
  7. // 创建时间:2008-9-23
  8. // 负责人:wangyp
  9. // 引用System.Configuration程序集
  10. // 在web.config文件
  11. /*
  12. <connectionStrings>
  13. <add name="constr" connectionString="Data Source=.;uid=sa;pwd=;Initial Catalog=OA_DB" providerName="System.Data.Client"/>
  14. </connectionStrings>
  15. */
  16. // ===================================================================
  17. using System;
  18. using System.Data;
  19. using System.Xml;
  20. using System.Data.SqlClient;
  21. using System.Collections;
  22. namespace COM.OA.SqlServerDAL
  23. {
  24.     /// <summary>
  25.     /// The Conn class 
  26.     /// </summary>
  27.     public static class Conn
  28.     {
  29.         public static readonly string SqlConn = System.Configuration.ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
  30.     }
  31.     /// <summary>
  32.     /// The SqlHelper class is intended to encapsulate high performance, scalable best practices for 
  33.     /// common uses of SqlClient.
  34.     /// </summary>
  35.     public sealed class SqlHelper
  36.     {
  37.         #region private utility methods & constructors
  38.         //Since this class provides only static methods, make the default constructor private to prevent 
  39.         //instances from being created with "new SqlHelper()".
  40.         private SqlHelper() { }
  41.         /// <summary>
  42.         /// This method is used to attach array of SqlParameters to a SqlCommand.
  43.         /// 
  44.         /// This method will assign a value of DbNull to any parameter with a direction of
  45.         /// InputOutput and a value of null.  
  46.         /// 
  47.         /// This behavior will prevent default values from being used, but
  48.         /// this will be the less common case than an intended pure output parameter (derived as InputOutput)
  49.         /// where the user provided no input value.
  50.         /// </summary>
  51.         /// <param name="command">The command to which the parameters will be added</param>
  52.         /// <param name="commandParameters">an array of SqlParameters tho be added to command</param>
  53.         private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
  54.         {
  55.             foreach (SqlParameter p in commandParameters)
  56.             {
  57.                 //check for derived output value with no value assigned
  58.                 if ((p.Direction == ParameterDirection.InputOutput) && (p.Value == null))
  59.                 {
  60.                     p.Value = DBNull.Value;
  61.                 }
  62.                 command.Parameters.Add(p);
  63.             }
  64.         }
  65.         /// <summary>
  66.         /// This method assigns an array of values to an array of SqlParameters.
  67.         /// </summary>
  68.         /// <param name="commandParameters">array of SqlParameters to be assigned values</param>
  69.         /// <param name="parameterValues">array of objects holding the values to be assigned</param>
  70.         private static void AssignParameterValues(SqlParameter[] commandParameters, object[] parameterValues)
  71.         {
  72.             if ((commandParameters == null) || (parameterValues == null))
  73.             {
  74.                 //do nothing if we get no data
  75.                 return;
  76.             }
  77.             // we must have the same number of values as we pave parameters to put them in
  78.             if (commandParameters.Length != parameterValues.Length)
  79.             {
  80.                 throw new ArgumentException("Parameter count does not match Parameter Value count.");
  81.             }
  82.             //iterate through the SqlParameters, assigning the values from the corresponding position in the 
  83.             //value array
  84.             for (int i = 0, j = commandParameters.Length; i < j; i++)
  85.             {
  86.                 commandParameters[i].Value = parameterValues[i];
  87.             }
  88.         }
  89.         /// <summary>
  90.         /// This method opens (if necessary) and assigns a connection, transaction, command type and parameters 
  91.         /// to the provided command.
  92.         /// </summary>
  93.         /// <param name="command">the SqlCommand to be prepared</param>
  94.         /// <param name="connection">a valid SqlConnection, on which to execute this command</param>
  95.         /// <param name="transaction">a valid SqlTransaction, or 'null'</param>
  96.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  97.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  98.         /// <param name="commandParameters">an array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
  99.         private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters)
  100.         {
  101.             //if the provided connection is not open, we will open it
  102.             if (connection.State != ConnectionState.Open)
  103.             {
  104.                 connection.Open();
  105.             }
  106.             //associate the connection with the command
  107.             command.Connection = connection;
  108.             //set the command text (stored procedure name or SQL statement)
  109.             command.CommandText = commandText;
  110.             //if we were provided a transaction, assign it.
  111.             if (transaction != null)
  112.             {
  113.                 command.Transaction = transaction;
  114.             }
  115.             //set the command type
  116.             command.CommandType = commandType;
  117.             //attach the command parameters if they are provided
  118.             if (commandParameters != null)
  119.             {
  120.                 AttachParameters(command, commandParameters);
  121.             }
  122.             return;
  123.         }
  124.         #endregion private utility methods & constructors
  125.         #region ExecuteNonQuery
  126.         /// <summary>
  127.         /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the database specified in 
  128.         /// the connection string. 
  129.         /// </summary>
  130.         /// <remarks>
  131.         /// e.g.:  
  132.         ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders");
  133.         /// </remarks>
  134.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  135.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  136.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  137.         /// <returns>an int representing the number of rows affected by the command</returns>
  138.         public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText)
  139.         {
  140.             //pass through the call providing null for the set of SqlParameters
  141.             return ExecuteNonQuery(connectionString, commandType, commandText, (SqlParameter[])null);
  142.         }
  143.         /// <summary>
  144.         /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string 
  145.         /// using the provided parameters.
  146.         /// </summary>
  147.         /// <remarks>
  148.         /// e.g.:  
  149.         ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
  150.         /// </remarks>
  151.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  152.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  153.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  154.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  155.         /// <returns>an int representing the number of rows affected by the command</returns>
  156.         public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  157.         {
  158.             //create & open a SqlConnection, and dispose of it after we are done.
  159.             using (SqlConnection cn = new SqlConnection(connectionString))
  160.             {
  161.                 cn.Open();
  162.                 //call the overload that takes a connection in place of the connection string
  163.                 return ExecuteNonQuery(cn, commandType, commandText, commandParameters);
  164.             }
  165.         }
  166.         /// <summary>
  167.         /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the database specified in 
  168.         /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
  169.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  170.         /// </summary>
  171.         /// <remarks>
  172.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  173.         /// 
  174.         /// e.g.:  
  175.         ///  int result = ExecuteNonQuery(connString, "PublishOrders", 24, 36);
  176.         /// </remarks>
  177.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  178.         /// <param name="spName">the name of the stored prcedure</param>
  179.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  180.         /// <returns>an int representing the number of rows affected by the command</returns>
  181.         public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)
  182.         {
  183.             //if we receive parameter values, we need to figure out where they go
  184.             if ((parameterValues != null) && (parameterValues.Length > 0))
  185.             {
  186.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  187.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
  188.                 //assign the provided values to these parameters based on parameter order
  189.                 AssignParameterValues(commandParameters, parameterValues);
  190.                 //call the overload that takes an array of SqlParameters
  191.                 return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
  192.             }
  193.             //otherwise we can just call the SP without params
  194.             else
  195.             {
  196.                 return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
  197.             }
  198.         }
  199.         /// <summary>
  200.         /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlConnection. 
  201.         /// </summary>
  202.         /// <remarks>
  203.         /// e.g.:  
  204.         ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders");
  205.         /// </remarks>
  206.         /// <param name="connection">a valid SqlConnection</param>
  207.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  208.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  209.         /// <returns>an int representing the number of rows affected by the command</returns>
  210.         public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText)
  211.         {
  212.             //pass through the call providing null for the set of SqlParameters
  213.             return ExecuteNonQuery(connection, commandType, commandText, (SqlParameter[])null);
  214.         }
  215.         /// <summary>
  216.         /// Execute a SqlCommand (that returns no resultset) against the specified SqlConnection 
  217.         /// using the provided parameters.
  218.         /// </summary>
  219.         /// <remarks>
  220.         /// e.g.:  
  221.         ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
  222.         /// </remarks>
  223.         /// <param name="connection">a valid SqlConnection</param>
  224.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  225.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  226.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  227.         /// <returns>an int representing the number of rows affected by the command</returns>
  228.         public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  229.         {
  230.             //create a command and prepare it for execution
  231.             SqlCommand cmd = new SqlCommand();
  232.             PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
  233.             //finally, execute the command.
  234.             int retval = cmd.ExecuteNonQuery();
  235.             // detach the SqlParameters from the command object, so they can be used again.
  236.             cmd.Parameters.Clear();
  237.             return retval;
  238.         }
  239.         /// <summary>
  240.         /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified SqlConnection 
  241.         /// using the provided parameter values.  This method will query the database to discover the parameters for the 
  242.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  243.         /// </summary>
  244.         /// <remarks>
  245.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  246.         /// 
  247.         /// e.g.:  
  248.         ///  int result = ExecuteNonQuery(conn, "PublishOrders", 24, 36);
  249.         /// </remarks>
  250.         /// <param name="connection">a valid SqlConnection</param>
  251.         /// <param name="spName">the name of the stored procedure</param>
  252.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  253.         /// <returns>an int representing the number of rows affected by the command</returns>
  254.         public static int ExecuteNonQuery(SqlConnection connection, string spName, params object[] parameterValues)
  255.         {
  256.             //if we receive parameter values, we need to figure out where they go
  257.             if ((parameterValues != null) && (parameterValues.Length > 0))
  258.             {
  259.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  260.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
  261.                 //assign the provided values to these parameters based on parameter order
  262.                 AssignParameterValues(commandParameters, parameterValues);
  263.                 //call the overload that takes an array of SqlParameters
  264.                 return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
  265.             }
  266.             //otherwise we can just call the SP without params
  267.             else
  268.             {
  269.                 return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
  270.             }
  271.         }
  272.         /// <summary>
  273.         /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlTransaction. 
  274.         /// </summary>
  275.         /// <remarks>
  276.         /// e.g.:  
  277.         ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders");
  278.         /// </remarks>
  279.         /// <param name="transaction">a valid SqlTransaction</param>
  280.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  281.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  282.         /// <returns>an int representing the number of rows affected by the command</returns>
  283.         public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText)
  284.         {
  285.             //pass through the call providing null for the set of SqlParameters
  286.             return ExecuteNonQuery(transaction, commandType, commandText, (SqlParameter[])null);
  287.         }
  288.         /// <summary>
  289.         /// Execute a SqlCommand (that returns no resultset) against the specified SqlTransaction
  290.         /// using the provided parameters.
  291.         /// </summary>
  292.         /// <remarks>
  293.         /// e.g.:  
  294.         ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  295.         /// </remarks>
  296.         /// <param name="transaction">a valid SqlTransaction</param>
  297.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  298.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  299.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  300.         /// <returns>an int representing the number of rows affected by the command</returns>
  301.         public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  302.         {
  303.             //create a command and prepare it for execution
  304.             SqlCommand cmd = new SqlCommand();
  305.             PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
  306.             //finally, execute the command.
  307.             int retval = cmd.ExecuteNonQuery();
  308.             // detach the SqlParameters from the command object, so they can be used again.
  309.             cmd.Parameters.Clear();
  310.             return retval;
  311.         }
  312.         /// <summary>
  313.         /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified 
  314.         /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
  315.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  316.         /// </summary>
  317.         /// <remarks>
  318.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  319.         /// 
  320.         /// e.g.:  
  321.         ///  int result = ExecuteNonQuery(conn, trans, "PublishOrders", 24, 36);
  322.         /// </remarks>
  323.         /// <param name="transaction">a valid SqlTransaction</param>
  324.         /// <param name="spName">the name of the stored procedure</param>
  325.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  326.         /// <returns>an int representing the number of rows affected by the command</returns>
  327.         public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
  328.         {
  329.             //if we receive parameter values, we need to figure out where they go
  330.             if ((parameterValues != null) && (parameterValues.Length > 0))
  331.             {
  332.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  333.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
  334.                 //assign the provided values to these parameters based on parameter order
  335.                 AssignParameterValues(commandParameters, parameterValues);
  336.                 //call the overload that takes an array of SqlParameters
  337.                 return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
  338.             }
  339.             //otherwise we can just call the SP without params
  340.             else
  341.             {
  342.                 return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
  343.             }
  344.         }
  345.         #endregion ExecuteNonQuery
  346.         #region ExecuteDataSet
  347.         public static void ExecuteDataset(SqlConnection connection, DataSet ds, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  348.         {
  349.             SqlCommand cmd = new SqlCommand();
  350.             PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
  351.             SqlDataAdapter da = new SqlDataAdapter(cmd);
  352.             for (int i = 0; i < ds.Tables.Count; ++i)
  353.             {
  354.                 if (i == 0)
  355.                     da.TableMappings.Add("Table", ds.Tables[i].TableName);
  356.                 else
  357.                     da.TableMappings.Add(string.Concat("Table", i.ToString()), ds.Tables[i].TableName);
  358.             }
  359.             da.Fill(ds);
  360.             cmd.Parameters.Clear();
  361.         }
  362.         //add by winsonchen 2004-04-20
  363.         public static void ExecuteDataset(string connectionString, DataSet ds, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  364.         {
  365.             using (SqlConnection cn = new SqlConnection(connectionString))
  366.             {
  367.                 cn.Open();
  368.                 SqlCommand cmd = new SqlCommand();
  369.                 PrepareCommand(cmd, cn, (SqlTransaction)null, commandType, commandText, commandParameters);
  370.                 SqlDataAdapter da = new SqlDataAdapter(cmd);
  371.                 for (int i = 0; i < ds.Tables.Count; ++i)
  372.                 {
  373.                     if (i == 0)
  374.                         da.TableMappings.Add("Table", ds.Tables[i].TableName);
  375.                     else
  376.                         da.TableMappings.Add(string.Concat("Table", i.ToString()), ds.Tables[i].TableName);
  377.                 }
  378.                 da.Fill(ds);
  379.                 cmd.Parameters.Clear();
  380.             }
  381.         }
  382.         /// <summary>
  383.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in 
  384.         /// the connection string. 
  385.         /// </summary>
  386.         /// <remarks>
  387.         /// e.g.:  
  388.         ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders");
  389.         /// </remarks>
  390.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  391.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  392.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  393.         /// <returns>a dataset containing the resultset generated by the command</returns>
  394.         public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText)
  395.         {
  396.             //pass through the call providing null for the set of SqlParameters
  397.             return ExecuteDataset(connectionString, commandType, commandText, (SqlParameter[])null);
  398.         }
  399.         /// <summary>
  400.         /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string 
  401.         /// using the provided parameters.
  402.         /// </summary>
  403.         /// <remarks>
  404.         /// e.g.:  
  405.         ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  406.         /// </remarks>
  407.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  408.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  409.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  410.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  411.         /// <returns>a dataset containing the resultset generated by the command</returns>
  412.         public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  413.         {
  414.             //create & open a SqlConnection, and dispose of it after we are done.
  415.             using (SqlConnection cn = new SqlConnection(connectionString))
  416.             {
  417.                 cn.Open();
  418.                 //call the overload that takes a connection in place of the connection string
  419.                 return ExecuteDataset(cn, commandType, commandText, commandParameters);
  420.             }
  421.         }
  422.         /// <summary>
  423.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
  424.         /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
  425.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  426.         /// </summary>
  427.         /// <remarks>
  428.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  429.         /// 
  430.         /// e.g.:  
  431.         ///  DataSet ds = ExecuteDataset(connString, "GetOrders", 24, 36);
  432.         /// </remarks>
  433.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  434.         /// <param name="spName">the name of the stored procedure</param>
  435.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  436.         /// <returns>a dataset containing the resultset generated by the command</returns>
  437.         public static DataSet ExecuteDataset(string connectionString, string spName, params object[] parameterValues)
  438.         {
  439.             //if we receive parameter values, we need to figure out where they go
  440.             if ((parameterValues != null) && (parameterValues.Length > 0))
  441.             {
  442.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  443.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
  444.                 //assign the provided values to these parameters based on parameter order
  445.                 AssignParameterValues(commandParameters, parameterValues);
  446.                 //call the overload that takes an array of SqlParameters
  447.                 return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
  448.             }
  449.             //otherwise we can just call the SP without params
  450.             else
  451.             {
  452.                 return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
  453.             }
  454.         }
  455.         /// <summary>
  456.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
  457.         /// </summary>
  458.         /// <remarks>
  459.         /// e.g.:  
  460.         ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders");
  461.         /// </remarks>
  462.         /// <param name="connection">a valid SqlConnection</param>
  463.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  464.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  465.         /// <returns>a dataset containing the resultset generated by the command</returns>
  466.         public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText)
  467.         {
  468.             //pass through the call providing null for the set of SqlParameters
  469.             return ExecuteDataset(connection, commandType, commandText, (SqlParameter[])null);
  470.         }
  471.         /// <summary>
  472.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
  473.         /// using the provided parameters.
  474.         /// </summary>
  475.         /// <remarks>
  476.         /// e.g.:  
  477.         ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  478.         /// </remarks>
  479.         /// <param name="connection">a valid SqlConnection</param>
  480.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  481.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  482.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  483.         /// <returns>a dataset containing the resultset generated by the command</returns>
  484.         public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  485.         {
  486.             //create a command and prepare it for execution
  487.             SqlCommand cmd = new SqlCommand();
  488.             PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
  489.             //create the DataAdapter & DataSet
  490.             SqlDataAdapter da = new SqlDataAdapter(cmd);
  491.             DataSet ds = new DataSet();
  492.             //fill the DataSet using default values for DataTable names, etc.
  493.             da.Fill(ds);
  494.             // detach the SqlParameters from the command object, so they can be used again.
  495.             cmd.Parameters.Clear();
  496.             //return the dataset
  497.             return ds;
  498.         }
  499.         /// <summary>
  500.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
  501.         /// using the provided parameter values.  This method will query the database to discover the parameters for the 
  502.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  503.         /// </summary>
  504.         /// <remarks>
  505.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  506.         /// 
  507.         /// e.g.:  
  508.         ///  DataSet ds = ExecuteDataset(conn, "GetOrders", 24, 36);
  509.         /// </remarks>
  510.         /// <param name="connection">a valid SqlConnection</param>
  511.         /// <param name="spName">the name of the stored procedure</param>
  512.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  513.         /// <returns>a dataset containing the resultset generated by the command</returns>
  514.         public static DataSet ExecuteDataset(SqlConnection connection, string spName, params object[] parameterValues)
  515.         {
  516.             //if we receive parameter values, we need to figure out where they go
  517.             if ((parameterValues != null) && (parameterValues.Length > 0))
  518.             {
  519.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  520.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
  521.                 //assign the provided values to these parameters based on parameter order
  522.                 AssignParameterValues(commandParameters, parameterValues);
  523.                 //call the overload that takes an array of SqlParameters
  524.                 return ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
  525.             }
  526.             //otherwise we can just call the SP without params
  527.             else
  528.             {
  529.                 return ExecuteDataset(connection, CommandType.StoredProcedure, spName);
  530.             }
  531.         }
  532.         /// <summary>
  533.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
  534.         /// </summary>
  535.         /// <remarks>
  536.         /// e.g.:  
  537.         ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders");
  538.         /// </remarks>
  539.         /// <param name="transaction">a valid SqlTransaction</param>
  540.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  541.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  542.         /// <returns>a dataset containing the resultset generated by the command</returns>
  543.         public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText)
  544.         {
  545.             //pass through the call providing null for the set of SqlParameters
  546.             return ExecuteDataset(transaction, commandType, commandText, (SqlParameter[])null);
  547.         }
  548.         /// <summary>
  549.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
  550.         /// using the provided parameters.
  551.         /// </summary>
  552.         /// <remarks>
  553.         /// e.g.:  
  554.         ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  555.         /// </remarks>
  556.         /// <param name="transaction">a valid SqlTransaction</param>
  557.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  558.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  559.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  560.         /// <returns>a dataset containing the resultset generated by the command</returns>
  561.         public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  562.         {
  563.             //create a command and prepare it for execution
  564.             SqlCommand cmd = new SqlCommand();
  565.             PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
  566.             //create the DataAdapter & DataSet
  567.             SqlDataAdapter da = new SqlDataAdapter(cmd);
  568.             DataSet ds = new DataSet();
  569.             //fill the DataSet using default values for DataTable names, etc.
  570.             da.Fill(ds);
  571.             // detach the SqlParameters from the command object, so they can be used again.
  572.             cmd.Parameters.Clear();
  573.             //return the dataset
  574.             return ds;
  575.         }
  576.         /// <summary>
  577.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified 
  578.         /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
  579.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  580.         /// </summary>
  581.         /// <remarks>
  582.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  583.         /// 
  584.         /// e.g.:  
  585.         ///  DataSet ds = ExecuteDataset(trans, "GetOrders", 24, 36);
  586.         /// </remarks>
  587.         /// <param name="transaction">a valid SqlTransaction</param>
  588.         /// <param name="spName">the name of the stored procedure</param>
  589.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  590.         /// <returns>a dataset containing the resultset generated by the command</returns>
  591.         public static DataSet ExecuteDataset(SqlTransaction transaction, string spName, params object[] parameterValues)
  592.         {
  593.             //if we receive parameter values, we need to figure out where they go
  594.             if ((parameterValues != null) && (parameterValues.Length > 0))
  595.             {
  596.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  597.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
  598.                 //assign the provided values to these parameters based on parameter order
  599.                 AssignParameterValues(commandParameters, parameterValues);
  600.                 //call the overload that takes an array of SqlParameters
  601.                 return ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
  602.             }
  603.             //otherwise we can just call the SP without params
  604.             else
  605.             {
  606.                 return ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
  607.             }
  608.         }
  609.         #endregion ExecuteDataSet
  610.         #region ExecuteReader
  611.         /// <summary>
  612.         /// this enum is used to indicate whether the connection was provided by the caller, or created by SqlHelper, so that
  613.         /// we can set the appropriate CommandBehavior when calling ExecuteReader()
  614.         /// </summary>
  615.         private enum SqlConnectionOwnership
  616.         {
  617.             /// <summary>Connection is owned and managed by SqlHelper</summary>
  618.             Internal,
  619.             /// <summary>Connection is owned and managed by the caller</summary>
  620.             External
  621.         }
  622.         /// <summary>
  623.         /// Create and prepare a SqlCommand, and call ExecuteReader with the appropriate CommandBehavior.
  624.         /// </summary>
  625.         /// <remarks>
  626.         /// If we created and opened the connection, we want the connection to be closed when the DataReader is closed.
  627.         /// 
  628.         /// If the caller provided the connection, we want to leave it to them to manage.
  629.         /// </remarks>
  630.         /// <param name="connection">a valid SqlConnection, on which to execute this command</param>
  631.         /// <param name="transaction">a valid SqlTransaction, or 'null'</param>
  632.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  633.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  634.         /// <param name="commandParameters">an array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
  635.         /// <param name="connectionOwnership">indicates whether the connection parameter was provided by the caller, or created by SqlHelper</param>
  636.         /// <returns>SqlDataReader containing the results of the command</returns>
  637.         private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)
  638.         {
  639.             //create a command and prepare it for execution
  640.             SqlCommand cmd = new SqlCommand();
  641.             PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters);
  642.             //create a reader
  643.             SqlDataReader dr;
  644.             // call ExecuteReader with the appropriate CommandBehavior
  645.             if (connectionOwnership == SqlConnectionOwnership.External)
  646.             {
  647.                 dr = cmd.ExecuteReader();
  648.             }
  649.             else
  650.             {
  651.                 dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  652.             }
  653.             // detach the SqlParameters from the command object, so they can be used again.
  654.             cmd.Parameters.Clear();
  655.             return dr;
  656.         }
  657.         /// <summary>
  658.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in 
  659.         /// the connection string. 
  660.         /// </summary>
  661.         /// <remarks>
  662.         /// e.g.:  
  663.         ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders");
  664.         /// </remarks>
  665.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  666.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  667.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  668.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  669.         public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText)
  670.         {
  671.             //pass through the call providing null for the set of SqlParameters
  672.             return ExecuteReader(connectionString, commandType, commandText, (SqlParameter[])null);
  673.         }
  674.         /// <summary>
  675.         /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string 
  676.         /// using the provided parameters.
  677.         /// </summary>
  678.         /// <remarks>
  679.         /// e.g.:  
  680.         ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  681.         /// </remarks>
  682.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  683.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  684.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  685.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  686.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  687.         public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  688.         {
  689.             //create & open a SqlConnection
  690.             SqlConnection cn = new SqlConnection(connectionString);
  691.             cn.Open();
  692.             try
  693.             {
  694.                 //call the private overload that takes an internally owned connection in place of the connection string
  695.                 return ExecuteReader(cn, null, commandType, commandText, commandParameters, SqlConnectionOwnership.Internal);
  696.             }
  697.             catch
  698.             {
  699.                 //if we fail to return the SqlDatReader, we need to close the connection ourselves
  700.                 cn.Close();
  701.                 throw;
  702.             }
  703.         }
  704.         /// <summary>
  705.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
  706.         /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
  707.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  708.         /// </summary>
  709.         /// <remarks>
  710.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  711.         /// 
  712.         /// e.g.:  
  713.         ///  SqlDataReader dr = ExecuteReader(connString, "GetOrders", 24, 36);
  714.         /// </remarks>
  715.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  716.         /// <param name="spName">the name of the stored procedure</param>
  717.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  718.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  719.         public static SqlDataReader ExecuteReader(string connectionString, string spName, params object[] parameterValues)
  720.         {
  721.             //if we receive parameter values, we need to figure out where they go
  722.             if ((parameterValues != null) && (parameterValues.Length > 0))
  723.             {
  724.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  725.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
  726.                 //assign the provided values to these parameters based on parameter order
  727.                 AssignParameterValues(commandParameters, parameterValues);
  728.                 //call the overload that takes an array of SqlParameters
  729.                 return ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
  730.             }
  731.             //otherwise we can just call the SP without params
  732.             else
  733.             {
  734.                 return ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
  735.             }
  736.         }
  737.         /// <summary>
  738.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
  739.         /// </summary>
  740.         /// <remarks>
  741.         /// e.g.:  
  742.         ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders");
  743.         /// </remarks>
  744.         /// <param name="connection">a valid SqlConnection</param>
  745.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  746.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  747.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  748.         public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText)
  749.         {
  750.             //pass through the call providing null for the set of SqlParameters
  751.             return ExecuteReader(connection, commandType, commandText, (SqlParameter[])null);
  752.         }
  753.         /// <summary>
  754.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
  755.         /// using the provided parameters.
  756.         /// </summary>
  757.         /// <remarks>
  758.         /// e.g.:  
  759.         ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  760.         /// </remarks>
  761.         /// <param name="connection">a valid SqlConnection</param>
  762.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  763.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  764.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  765.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  766.         public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  767.         {
  768.             //pass through the call to the private overload using a null transaction value and an externally owned connection
  769.             return ExecuteReader(connection, (SqlTransaction)null, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
  770.         }
  771.         /// <summary>
  772.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
  773.         /// using the provided parameter values.  This method will query the database to discover the parameters for the 
  774.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  775.         /// </summary>
  776.         /// <remarks>
  777.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  778.         /// 
  779.         /// e.g.:  
  780.         ///  SqlDataReader dr = ExecuteReader(conn, "GetOrders", 24, 36);
  781.         /// </remarks>
  782.         /// <param name="connection">a valid SqlConnection</param>
  783.         /// <param name="spName">the name of the stored procedure</param>
  784.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  785.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  786.         public static SqlDataReader ExecuteReader(SqlConnection connection, string spName, params object[] parameterValues)
  787.         {
  788.             //if we receive parameter values, we need to figure out where they go
  789.             if ((parameterValues != null) && (parameterValues.Length > 0))
  790.             {
  791.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
  792.                 AssignParameterValues(commandParameters, parameterValues);
  793.                 return ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
  794.             }
  795.             //otherwise we can just call the SP without params
  796.             else
  797.             {
  798.                 return ExecuteReader(connection, CommandType.StoredProcedure, spName);
  799.             }
  800.         }
  801.         /// <summary>
  802.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
  803.         /// </summary>
  804.         /// <remarks>
  805.         /// e.g.:  
  806.         ///  SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders");
  807.         /// </remarks>
  808.         /// <param name="transaction">a valid SqlTransaction</param>
  809.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  810.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  811.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  812.         public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText)
  813.         {
  814.             //pass through the call providing null for the set of SqlParameters
  815.             return ExecuteReader(transaction, commandType, commandText, (SqlParameter[])null);
  816.         }
  817.         /// <summary>
  818.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
  819.         /// using the provided parameters.
  820.         /// </summary>
  821.         /// <remarks>
  822.         /// e.g.:  
  823.         ///   SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  824.         /// </remarks>
  825.         /// <param name="transaction">a valid SqlTransaction</param>
  826.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  827.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  828.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  829.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  830.         public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  831.         {
  832.             //pass through to private overload, indicating that the connection is owned by the caller
  833.             return ExecuteReader(transaction.Connection, transaction, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
  834.         }
  835.         /// <summary>
  836.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified
  837.         /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
  838.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  839.         /// </summary>
  840.         /// <remarks>
  841.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  842.         /// 
  843.         /// e.g.:  
  844.         ///  SqlDataReader dr = ExecuteReader(trans, "GetOrders", 24, 36);
  845.         /// </remarks>
  846.         /// <param name="transaction">a valid SqlTransaction</param>
  847.         /// <param name="spName">the name of the stored procedure</param>
  848.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  849.         /// <returns>a SqlDataReader containing the resultset generated by the command</returns>
  850.         public static SqlDataReader ExecuteReader(SqlTransaction transaction, string spName, params object[] parameterValues)
  851.         {
  852.             //if we receive parameter values, we need to figure out where they go
  853.             if ((parameterValues != null) && (parameterValues.Length > 0))
  854.             {
  855.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
  856.                 AssignParameterValues(commandParameters, parameterValues);
  857.                 return ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
  858.             }
  859.             //otherwise we can just call the SP without params
  860.             else
  861.             {
  862.                 return ExecuteReader(transaction, CommandType.StoredProcedure, spName);
  863.             }
  864.         }
  865.         #endregion ExecuteReader
  866.         #region ExecuteScalar
  867.         /// <summary>
  868.         /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the database specified in 
  869.         /// the connection string. 
  870.         /// </summary>
  871.         /// <remarks>
  872.         /// e.g.:  
  873.         ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount");
  874.         /// </remarks>
  875.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  876.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  877.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  878.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  879.         public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText)
  880.         {
  881.             //pass through the call providing null for the set of SqlParameters
  882.             return ExecuteScalar(connectionString, commandType, commandText, (SqlParameter[])null);
  883.         }
  884.         /// <summary>
  885.         /// Execute a SqlCommand (that returns a 1x1 resultset) against the database specified in the connection string 
  886.         /// using the provided parameters.
  887.         /// </summary>
  888.         /// <remarks>
  889.         /// e.g.:  
  890.         ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
  891.         /// </remarks>
  892.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  893.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  894.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  895.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  896.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  897.         public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  898.         {
  899.             //create & open a SqlConnection, and dispose of it after we are done.
  900.             using (SqlConnection cn = new SqlConnection(connectionString))
  901.             {
  902.                 cn.Open();
  903.                 //call the overload that takes a connection in place of the connection string
  904.                 return ExecuteScalar(cn, commandType, commandText, commandParameters);
  905.             }
  906.         }
  907.         /// <summary>
  908.         /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the database specified in 
  909.         /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
  910.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  911.         /// </summary>
  912.         /// <remarks>
  913.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  914.         /// 
  915.         /// e.g.:  
  916.         ///  int orderCount = (int)ExecuteScalar(connString, "GetOrderCount", 24, 36);
  917.         /// </remarks>
  918.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  919.         /// <param name="spName">the name of the stored procedure</param>
  920.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  921.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  922.         public static object ExecuteScalar(string connectionString, string spName, params object[] parameterValues)
  923.         {
  924.             //if we receive parameter values, we need to figure out where they go
  925.             if ((parameterValues != null) && (parameterValues.Length > 0))
  926.             {
  927.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  928.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
  929.                 //assign the provided values to these parameters based on parameter order
  930.                 AssignParameterValues(commandParameters, parameterValues);
  931.                 //call the overload that takes an array of SqlParameters
  932.                 return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
  933.             }
  934.             //otherwise we can just call the SP without params
  935.             else
  936.             {
  937.                 return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
  938.             }
  939.         }
  940.         /// <summary>
  941.         /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlConnection. 
  942.         /// </summary>
  943.         /// <remarks>
  944.         /// e.g.:  
  945.         ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount");
  946.         /// </remarks>
  947.         /// <param name="connection">a valid SqlConnection</param>
  948.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  949.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  950.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  951.         public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText)
  952.         {
  953.             //pass through the call providing null for the set of SqlParameters
  954.             return ExecuteScalar(connection, commandType, commandText, (SqlParameter[])null);
  955.         }
  956.         /// <summary>
  957.         /// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection 
  958.         /// using the provided parameters.
  959.         /// </summary>
  960.         /// <remarks>
  961.         /// e.g.:  
  962.         ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
  963.         /// </remarks>
  964.         /// <param name="connection">a valid SqlConnection</param>
  965.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  966.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  967.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  968.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  969.         public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  970.         {
  971.             //create a command and prepare it for execution
  972.             SqlCommand cmd = new SqlCommand();
  973.             PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
  974.             //execute the command & return the results
  975.             object retval = cmd.ExecuteScalar();
  976.             // detach the SqlParameters from the command object, so they can be used again.
  977.             cmd.Parameters.Clear();
  978.             return retval;
  979.         }
  980.         /// <summary>
  981.         /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection 
  982.         /// using the provided parameter values.  This method will query the database to discover the parameters for the 
  983.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  984.         /// </summary>
  985.         /// <remarks>
  986.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  987.         /// 
  988.         /// e.g.:  
  989.         ///  int orderCount = (int)ExecuteScalar(conn, "GetOrderCount", 24, 36);
  990.         /// </remarks>
  991.         /// <param name="connection">a valid SqlConnection</param>
  992.         /// <param name="spName">the name of the stored procedure</param>
  993.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  994.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  995.         public static object ExecuteScalar(SqlConnection connection, string spName, params object[] parameterValues)
  996.         {
  997.             //if we receive parameter values, we need to figure out where they go
  998.             if ((parameterValues != null) && (parameterValues.Length > 0))
  999.             {
  1000.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  1001.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
  1002.                 //assign the provided values to these parameters based on parameter order
  1003.                 AssignParameterValues(commandParameters, parameterValues);
  1004.                 //call the overload that takes an array of SqlParameters
  1005.                 return ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
  1006.             }
  1007.             //otherwise we can just call the SP without params
  1008.             else
  1009.             {
  1010.                 return ExecuteScalar(connection, CommandType.StoredProcedure, spName);
  1011.             }
  1012.         }
  1013.         /// <summary>
  1014.         /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlTransaction. 
  1015.         /// </summary>
  1016.         /// <remarks>
  1017.         /// e.g.:  
  1018.         ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount");
  1019.         /// </remarks>
  1020.         /// <param name="transaction">a valid SqlTransaction</param>
  1021.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1022.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  1023.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  1024.         public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText)
  1025.         {
  1026.             //pass through the call providing null for the set of SqlParameters
  1027.             return ExecuteScalar(transaction, commandType, commandText, (SqlParameter[])null);
  1028.         }
  1029.         /// <summary>
  1030.         /// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlTransaction
  1031.         /// using the provided parameters.
  1032.         /// </summary>
  1033.         /// <remarks>
  1034.         /// e.g.:  
  1035.         ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
  1036.         /// </remarks>
  1037.         /// <param name="transaction">a valid SqlTransaction</param>
  1038.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1039.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  1040.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  1041.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  1042.         public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  1043.         {
  1044.             //create a command and prepare it for execution
  1045.             SqlCommand cmd = new SqlCommand();
  1046.             PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
  1047.             //execute the command & return the results
  1048.             object retval = cmd.ExecuteScalar();
  1049.             // detach the SqlParameters from the command object, so they can be used again.
  1050.             cmd.Parameters.Clear();
  1051.             return retval;
  1052.         }
  1053.         /// <summary>
  1054.         /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified
  1055.         /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
  1056.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  1057.         /// </summary>
  1058.         /// <remarks>
  1059.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  1060.         /// 
  1061.         /// e.g.:  
  1062.         ///  int orderCount = (int)ExecuteScalar(trans, "GetOrderCount", 24, 36);
  1063.         /// </remarks>
  1064.         /// <param name="transaction">a valid SqlTransaction</param>
  1065.         /// <param name="spName">the name of the stored procedure</param>
  1066.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  1067.         /// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
  1068.         public static object ExecuteScalar(SqlTransaction transaction, string spName, params object[] parameterValues)
  1069.         {
  1070.             //if we receive parameter values, we need to figure out where they go
  1071.             if ((parameterValues != null) && (parameterValues.Length > 0))
  1072.             {
  1073.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  1074.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
  1075.                 //assign the provided values to these parameters based on parameter order
  1076.                 AssignParameterValues(commandParameters, parameterValues);
  1077.                 //call the overload that takes an array of SqlParameters
  1078.                 return ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
  1079.             }
  1080.             //otherwise we can just call the SP without params
  1081.             else
  1082.             {
  1083.                 return ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
  1084.             }
  1085.         }
  1086.         #endregion ExecuteScalar
  1087.         #region ExecuteXmlReader
  1088.         /// <summary>
  1089.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
  1090.         /// </summary>
  1091.         /// <remarks>
  1092.         /// e.g.:  
  1093.         ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders");
  1094.         /// </remarks>
  1095.         /// <param name="connection">a valid SqlConnection</param>
  1096.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1097.         /// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
  1098.         /// <returns>an XmlReader containing the resultset generated by the command</returns>
  1099.         public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText)
  1100.         {
  1101.             //pass through the call providing null for the set of SqlParameters
  1102.             return ExecuteXmlReader(connection, commandType, commandText, (SqlParameter[])null);
  1103.         }
  1104.         /// <summary>
  1105.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
  1106.         /// using the provided parameters.
  1107.         /// </summary>
  1108.         /// <remarks>
  1109.         /// e.g.:  
  1110.         ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  1111.         /// </remarks>
  1112.         /// <param name="connection">a valid SqlConnection</param>
  1113.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1114.         /// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
  1115.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  1116.         /// <returns>an XmlReader containing the resultset generated by the command</returns>
  1117.         public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  1118.         {
  1119.             //create a command and prepare it for execution
  1120.             SqlCommand cmd = new SqlCommand();
  1121.             PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
  1122.             //create the DataAdapter & DataSet
  1123.             XmlReader retval = cmd.ExecuteXmlReader();
  1124.             // detach the SqlParameters from the command object, so they can be used again.
  1125.             cmd.Parameters.Clear();
  1126.             return retval;
  1127.         }
  1128.         /// <summary>
  1129.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
  1130.         /// using the provided parameter values.  This method will query the database to discover the parameters for the 
  1131.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  1132.         /// </summary>
  1133.         /// <remarks>
  1134.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  1135.         /// 
  1136.         /// e.g.:  
  1137.         ///  XmlReader r = ExecuteXmlReader(conn, "GetOrders", 24, 36);
  1138.         /// </remarks>
  1139.         /// <param name="connection">a valid SqlConnection</param>
  1140.         /// <param name="spName">the name of the stored procedure using "FOR XML AUTO"</param>
  1141.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  1142.         /// <returns>an XmlReader containing the resultset generated by the command</returns>
  1143.         public static XmlReader ExecuteXmlReader(SqlConnection connection, string spName, params object[] parameterValues)
  1144.         {
  1145.             //if we receive parameter values, we need to figure out where they go
  1146.             if ((parameterValues != null) && (parameterValues.Length > 0))
  1147.             {
  1148.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  1149.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
  1150.                 //assign the provided values to these parameters based on parameter order
  1151.                 AssignParameterValues(commandParameters, parameterValues);
  1152.                 //call the overload that takes an array of SqlParameters
  1153.                 return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
  1154.             }
  1155.             //otherwise we can just call the SP without params
  1156.             else
  1157.             {
  1158.                 return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
  1159.             }
  1160.         }
  1161.         /// <summary>
  1162.         /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
  1163.         /// </summary>
  1164.         /// <remarks>
  1165.         /// e.g.:  
  1166.         ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders");
  1167.         /// </remarks>
  1168.         /// <param name="transaction">a valid SqlTransaction</param>
  1169.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1170.         /// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
  1171.         /// <returns>an XmlReader containing the resultset generated by the command</returns>
  1172.         public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText)
  1173.         {
  1174.             //pass through the call providing null for the set of SqlParameters
  1175.             return ExecuteXmlReader(transaction, commandType, commandText, (SqlParameter[])null);
  1176.         }
  1177.         /// <summary>
  1178.         /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
  1179.         /// using the provided parameters.
  1180.         /// </summary>
  1181.         /// <remarks>
  1182.         /// e.g.:  
  1183.         ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
  1184.         /// </remarks>
  1185.         /// <param name="transaction">a valid SqlTransaction</param>
  1186.         /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
  1187.         /// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
  1188.         /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
  1189.         /// <returns>an XmlReader containing the resultset generated by the command</returns>
  1190.         public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
  1191.         {
  1192.             //create a command and prepare it for execution
  1193.             SqlCommand cmd = new SqlCommand();
  1194.             PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
  1195.             //create the DataAdapter & DataSet
  1196.             XmlReader retval = cmd.ExecuteXmlReader();
  1197.             // detach the SqlParameters from the command object, so they can be used again.
  1198.             cmd.Parameters.Clear();
  1199.             return retval;
  1200.         }
  1201.         /// <summary>
  1202.         /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified 
  1203.         /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
  1204.         /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
  1205.         /// </summary>
  1206.         /// <remarks>
  1207.         /// This method provides no access to output parameters or the stored procedure's return value parameter.
  1208.         /// 
  1209.         /// e.g.:  
  1210.         ///  XmlReader r = ExecuteXmlReader(trans, "GetOrders", 24, 36);
  1211.         /// </remarks>
  1212.         /// <param name="transaction">a valid SqlTransaction</param>
  1213.         /// <param name="spName">the name of the stored procedure</param>
  1214.         /// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
  1215.         /// <returns>a dataset containing the resultset generated by the command</returns>
  1216.         public static XmlReader ExecuteXmlReader(SqlTransaction transaction, string spName, params object[] parameterValues)
  1217.         {
  1218.             //if we receive parameter values, we need to figure out where they go
  1219.             if ((parameterValues != null) && (parameterValues.Length > 0))
  1220.             {
  1221.                 //pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
  1222.                 SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
  1223.                 //assign the provided values to these parameters based on parameter order
  1224.                 AssignParameterValues(commandParameters, parameterValues);
  1225.                 //call the overload that takes an array of SqlParameters
  1226.                 return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
  1227.             }
  1228.             //otherwise we can just call the SP without params
  1229.             else
  1230.             {
  1231.                 return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
  1232.             }
  1233.         }
  1234.         #endregion ExecuteXmlReader
  1235.     }
  1236.     /// <summary>
  1237.     /// SqlHelperParameterCache provides functions to leverage a static cache of procedure parameters, and the
  1238.     /// ability to discover parameters for stored procedures at run-time.
  1239.     /// </summary>
  1240.     public sealed class SqlHelperParameterCache
  1241.     {
  1242.         #region private methods, variables, and constructors
  1243.         //Since this class provides only static methods, make the default constructor private to prevent 
  1244.         //instances from being created with "new SqlHelperParameterCache()".
  1245.         private SqlHelperParameterCache() { }
  1246.         private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
  1247.         /// <summary>
  1248.         /// resolve at run time the appropriate set of SqlParameters for a stored procedure
  1249.         /// </summary>
  1250.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  1251.         /// <param name="spName">the name of the stored procedure</param>
  1252.         /// <param name="includeReturnValueParameter">whether or not to include their return value parameter</param>
  1253.         /// <returns></returns>
  1254.         private static SqlParameter[] DiscoverSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
  1255.         {
  1256.             using (SqlConnection cn = new SqlConnection(connectionString))
  1257.             using (SqlCommand cmd = new SqlCommand(spName, cn))
  1258.             {
  1259.                 cn.Open();
  1260.                 cmd.CommandType = CommandType.StoredProcedure;
  1261.                 SqlCommandBuilder.DeriveParameters(cmd);
  1262.                 if (!includeReturnValueParameter)
  1263.                 {
  1264.                     cmd.Parameters.RemoveAt(0);
  1265.                 }
  1266.                 SqlParameter[] discoveredParameters = new SqlParameter[cmd.Parameters.Count]; ;
  1267.                 cmd.Parameters.CopyTo(discoveredParameters, 0);
  1268.                 return discoveredParameters;
  1269.             }
  1270.         }
  1271.         //deep copy of cached SqlParameter array
  1272.         private static SqlParameter[] CloneParameters(SqlParameter[] originalParameters)
  1273.         {
  1274.             SqlParameter[] clonedParameters = new SqlParameter[originalParameters.Length];
  1275.             for (int i = 0, j = originalParameters.Length; i < j; i++)
  1276.             {
  1277.                 clonedParameters[i] = (SqlParameter)((ICloneable)originalParameters[i]).Clone();
  1278.             }
  1279.             return clonedParameters;
  1280.         }
  1281.         #endregion private methods, variables, and constructors
  1282.         #region caching functions
  1283.         /// <summary>
  1284.         /// add parameter array to the cache
  1285.         /// </summary>
  1286.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  1287.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  1288.         /// <param name="commandParameters">an array of SqlParamters to be cached</param>
  1289.         public static void CacheParameterSet(string connectionString, string commandText, params SqlParameter[] commandParameters)
  1290.         {
  1291.             string hashKey = connectionString + ":" + commandText;
  1292.             paramCache[hashKey] = commandParameters;
  1293.         }
  1294.         /// <summary>
  1295.         /// retrieve a parameter array from the cache
  1296.         /// </summary>
  1297.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  1298.         /// <param name="commandText">the stored procedure name or T-SQL command</param>
  1299.         /// <returns>an array of SqlParamters</returns>
  1300.         public static SqlParameter[] GetCachedParameterSet(string connectionString, string commandText)
  1301.         {
  1302.             string hashKey = connectionString + ":" + commandText;
  1303.             SqlParameter[] cachedParameters = (SqlParameter[])paramCache[hashKey];
  1304.             if (cachedParameters == null)
  1305.             {
  1306.                 return null;
  1307.             }
  1308.             else
  1309.             {
  1310.                 return CloneParameters(cachedParameters);
  1311.             }
  1312.         }
  1313.         #endregion caching functions
  1314.         #region Parameter Discovery Functions
  1315.         /// <summary>
  1316.         /// Retrieves the set of SqlParameters appropriate for the stored procedure
  1317.         /// </summary>
  1318.         /// <remarks>
  1319.         /// This method will query the database for this information, and then store it in a cache for future requests.
  1320.         /// </remarks>
  1321.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  1322.         /// <param name="spName">the name of the stored procedure</param>
  1323.         /// <returns>an array of SqlParameters</returns>
  1324.         public static SqlParameter[] GetSpParameterSet(string connectionString, string spName)
  1325.         {
  1326.             return GetSpParameterSet(connectionString, spName, false);
  1327.         }
  1328.         /// <summary>
  1329.         /// Retrieves the set of SqlParameters appropriate for the stored procedure
  1330.         /// </summary>
  1331.         /// <remarks>
  1332.         /// This method will query the database for this information, and then store it in a cache for future requests.
  1333.         /// </remarks>
  1334.         /// <param name="connectionString">a valid connection string for a SqlConnection</param>
  1335.         /// <param name="spName">the name of the stored procedure</param>
  1336.         /// <param name="includeReturnValueParameter">a bool value indicating whether the return value parameter should be included in the results</param>
  1337.         /// <returns>an array of SqlParameters</returns>
  1338.         public static SqlParameter[] GetSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
  1339.         {
  1340.             string hashKey = connectionString + ":" + spName + (includeReturnValueParameter ? ":include ReturnValue Parameter" : "");
  1341.             SqlParameter[] cachedParameters;
  1342.             cachedParameters = (SqlParameter[])paramCache[hashKey];
  1343.             if (cachedParameters == null)
  1344.             {
  1345.                 cachedParameters = (SqlParameter[])(paramCache[hashKey] = DiscoverSpParameterSet(connectionString, spName, includeReturnValueParameter));
  1346.             }
  1347.             return CloneParameters(cachedParameters);
  1348.         }
  1349.         #endregion Parameter Discovery Functions
  1350.     }
  1351. }