• [转]SqlHelper.cs


       1 // ===============================================================================
       2 // Microsoft Data Access Application Block for .NET
       3 // http://msdn.microsoft.com/library/en-us/dnbda/html/daab-rm.asp
       4 //
       5 // SQLHelper.cs
       6 //
       7 // This file contains the implementations of the SqlHelper and SqlHelperParameterCache
       8 // classes.
       9 //
      10 // For more information see the Data Access Application Block Implementation Overview. 
      11 // ===============================================================================
      12 // Release history
      13 // VERSION    DESCRIPTION
      14 //   2.0    Added support for FillDataset, UpdateDataset and "Param" helper methods
      15 //
      16 // ===============================================================================
      17 // Copyright (C) 2000-2001 Microsoft Corporation
      18 // All rights reserved.
      19 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
      20 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
      21 // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
      22 // FITNESS FOR A PARTICULAR PURPOSE.
      23 // ==============================================================================
      24 
      25 using System;
      26 using System.Data;
      27 using System.Xml;
      28 using System.Data.SqlClient;
      29 using System.Collections;
      30 
      31 namespace Microsoft.ApplicationBlocks.Data
      32 {
      33   /// <summary>
      34   /// The SqlHelper class is intended to encapsulate high performance, scalable best practices for 
      35   /// common uses of SqlClient
      36   /// </summary>
      37   public sealed class SqlHelper
      38   {
      39     #region private utility methods & constructors
      40 
      41     // Since this class provides only static methods, make the default constructor private to prevent 
      42     // instances from being created with "new SqlHelper()"
      43     private SqlHelper() { }
      44 
      45     /// <summary>
      46     /// This method is used to attach array of SqlParameters to a SqlCommand.
      47     /// 
      48     /// This method will assign a value of DbNull to any parameter with a direction of
      49     /// InputOutput and a value of null.  
      50     /// 
      51     /// This behavior will prevent default values from being used, but
      52     /// this will be the less common case than an intended pure output parameter (derived as InputOutput)
      53     /// where the user provided no input value.
      54     /// </summary>
      55     /// <param name="command">The command to which the parameters will be added</param>
      56     /// <param name="commandParameters">An array of SqlParameters to be added to command</param>
      57     private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
      58     {
      59       if (command == null) throw new ArgumentNullException("command");
      60       if (commandParameters != null)
      61       {
      62         foreach (SqlParameter p in commandParameters)
      63         {
      64           if (p != null)
      65           {
      66             // Check for derived output value with no value assigned
      67             if ((p.Direction == ParameterDirection.InputOutput ||
      68               p.Direction == ParameterDirection.Input) &&
      69               (p.Value == null))
      70             {
      71               p.Value = DBNull.Value;
      72             }
      73             command.Parameters.Add(p);
      74           }
      75         }
      76       }
      77     }
      78 
      79     /// <summary>
      80     /// This method assigns dataRow column values to an array of SqlParameters
      81     /// </summary>
      82     /// <param name="commandParameters">Array of SqlParameters to be assigned values</param>
      83     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values</param>
      84     private static void AssignParameterValues(SqlParameter[] commandParameters, DataRow dataRow)
      85     {
      86       if ((commandParameters == null) || (dataRow == null))
      87       {
      88         // Do nothing if we get no data
      89         return;
      90       }
      91 
      92       int i = 0;
      93       // Set the parameters values
      94       foreach (SqlParameter commandParameter in commandParameters)
      95       {
      96         // Check the parameter name
      97         if (commandParameter.ParameterName == null ||
      98           commandParameter.ParameterName.Length <= 1)
      99           throw new Exception(
     100             string.Format(
     101               "Please provide a valid parameter name on the parameter #{0}, the ParameterName property has the following value: '{1}'.",
     102               i, commandParameter.ParameterName));
     103         if (dataRow.Table.Columns.IndexOf(commandParameter.ParameterName.Substring(1)) != -1)
     104           commandParameter.Value = dataRow[commandParameter.ParameterName.Substring(1)];
     105         i++;
     106       }
     107     }
     108 
     109     /// <summary>
     110     /// This method assigns an array of values to an array of SqlParameters
     111     /// </summary>
     112     /// <param name="commandParameters">Array of SqlParameters to be assigned values</param>
     113     /// <param name="parameterValues">Array of objects holding the values to be assigned</param>
     114     private static void AssignParameterValues(SqlParameter[] commandParameters, object[] parameterValues)
     115     {
     116       if ((commandParameters == null) || (parameterValues == null))
     117       {
     118         // Do nothing if we get no data
     119         return;
     120       }
     121 
     122       // We must have the same number of values as we pave parameters to put them in
     123       if (commandParameters.Length != parameterValues.Length)
     124       {
     125         throw new ArgumentException("Parameter count does not match Parameter Value count.");
     126       }
     127 
     128       // Iterate through the SqlParameters, assigning the values from the corresponding position in the 
     129       // value array
     130       for (int i = 0, j = commandParameters.Length; i < j; i++)
     131       {
     132         // If the current array value derives from IDbDataParameter, then assign its Value property
     133         if (parameterValues[i] is IDbDataParameter)
     134         {
     135           IDbDataParameter paramInstance = (IDbDataParameter)parameterValues[i];
     136           if (paramInstance.Value == null)
     137           {
     138             commandParameters[i].Value = DBNull.Value;
     139           }
     140           else
     141           {
     142             commandParameters[i].Value = paramInstance.Value;
     143           }
     144         }
     145         else if (parameterValues[i] == null)
     146         {
     147           commandParameters[i].Value = DBNull.Value;
     148         }
     149         else
     150         {
     151           commandParameters[i].Value = parameterValues[i];
     152         }
     153       }
     154     }
     155 
     156     /// <summary>
     157     /// This method opens (if necessary) and assigns a connection, transaction, command type and parameters 
     158     /// to the provided command
     159     /// </summary>
     160     /// <param name="command">The SqlCommand to be prepared</param>
     161     /// <param name="connection">A valid SqlConnection, on which to execute this command</param>
     162     /// <param name="transaction">A valid SqlTransaction, or 'null'</param>
     163     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     164     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     165     /// <param name="commandParameters">An array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
     166     /// <param name="mustCloseConnection"><c>true</c> if the connection was opened by the method, otherwose is false.</param>
     167     private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, out bool mustCloseConnection)
     168     {
     169       if (command == null) throw new ArgumentNullException("command");
     170       if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
     171 
     172       // If the provided connection is not open, we will open it
     173       if (connection.State != ConnectionState.Open)
     174       {
     175         mustCloseConnection = true;
     176         connection.Open();
     177       }
     178       else
     179       {
     180         mustCloseConnection = false;
     181       }
     182 
     183       // Associate the connection with the command
     184       command.Connection = connection;
     185 
     186       // Set the command text (stored procedure name or SQL statement)
     187       command.CommandText = commandText;
     188 
     189       // If we were provided a transaction, assign it
     190       if (transaction != null)
     191       {
     192         if (transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
     193         command.Transaction = transaction;
     194       }
     195 
     196       // Set the command type
     197       command.CommandType = commandType;
     198 
     199       // Attach the command parameters if they are provided
     200       if (commandParameters != null)
     201       {
     202         AttachParameters(command, commandParameters);
     203       }
     204       return;
     205     }
     206 
     207     #endregion private utility methods & constructors
     208 
     209     #region ExecuteNonQuery
     210 
     211     /// <summary>
     212     /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the database specified in 
     213     /// the connection string
     214     /// </summary>
     215     /// <remarks>
     216     /// e.g.:  
     217     ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders");
     218     /// </remarks>
     219     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     220     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     221     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     222     /// <returns>An int representing the number of rows affected by the command</returns>
     223     public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText)
     224     {
     225       // Pass through the call providing null for the set of SqlParameters
     226       return ExecuteNonQuery(connectionString, commandType, commandText, (SqlParameter[])null);
     227     }
     228 
     229     /// <summary>
     230     /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string 
     231     /// using the provided parameters
     232     /// </summary>
     233     /// <remarks>
     234     /// e.g.:  
     235     ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
     236     /// </remarks>
     237     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     238     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     239     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     240     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     241     /// <returns>An int representing the number of rows affected by the command</returns>
     242     public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     243     {
     244       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     245 
     246       // Create & open a SqlConnection, and dispose of it after we are done
     247       using (SqlConnection connection = new SqlConnection(connectionString))
     248       {
     249         connection.Open();
     250 
     251         // Call the overload that takes a connection in place of the connection string
     252         return ExecuteNonQuery(connection, commandType, commandText, commandParameters);
     253       }
     254     }
     255 
     256     /// <summary>
     257     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the database specified in 
     258     /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
     259     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     260     /// </summary>
     261     /// <remarks>
     262     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     263     /// 
     264     /// e.g.:  
     265     ///  int result = ExecuteNonQuery(connString, "PublishOrders", 24, 36);
     266     /// </remarks>
     267     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     268     /// <param name="spName">The name of the stored prcedure</param>
     269     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     270     /// <returns>An int representing the number of rows affected by the command</returns>
     271     public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)
     272     {
     273       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     274       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     275 
     276       // If we receive parameter values, we need to figure out where they go
     277       if ((parameterValues != null) && (parameterValues.Length > 0))
     278       {
     279         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     280         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
     281 
     282         // Assign the provided values to these parameters based on parameter order
     283         AssignParameterValues(commandParameters, parameterValues);
     284 
     285         // Call the overload that takes an array of SqlParameters
     286         return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
     287       }
     288       else
     289       {
     290         // Otherwise we can just call the SP without params
     291         return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
     292       }
     293     }
     294 
     295     /// <summary>
     296     /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlConnection. 
     297     /// </summary>
     298     /// <remarks>
     299     /// e.g.:  
     300     ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders");
     301     /// </remarks>
     302     /// <param name="connection">A valid SqlConnection</param>
     303     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     304     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     305     /// <returns>An int representing the number of rows affected by the command</returns>
     306     public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText)
     307     {
     308       // Pass through the call providing null for the set of SqlParameters
     309       return ExecuteNonQuery(connection, commandType, commandText, (SqlParameter[])null);
     310     }
     311 
     312     /// <summary>
     313     /// Execute a SqlCommand (that returns no resultset) against the specified SqlConnection 
     314     /// using the provided parameters.
     315     /// </summary>
     316     /// <remarks>
     317     /// e.g.:  
     318     ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
     319     /// </remarks>
     320     /// <param name="connection">A valid SqlConnection</param>
     321     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     322     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     323     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     324     /// <returns>An int representing the number of rows affected by the command</returns>
     325     public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     326     {
     327       if (connection == null) throw new ArgumentNullException("connection");
     328 
     329       // Create a command and prepare it for execution
     330       SqlCommand cmd = new SqlCommand();
     331       bool mustCloseConnection = false;
     332       PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
     333 
     334       // Finally, execute the command
     335       int retval = cmd.ExecuteNonQuery();
     336 
     337       // Detach the SqlParameters from the command object, so they can be used again
     338       cmd.Parameters.Clear();
     339       if (mustCloseConnection)
     340         connection.Close();
     341       return retval;
     342     }
     343 
     344     /// <summary>
     345     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified SqlConnection 
     346     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
     347     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     348     /// </summary>
     349     /// <remarks>
     350     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     351     /// 
     352     /// e.g.:  
     353     ///  int result = ExecuteNonQuery(conn, "PublishOrders", 24, 36);
     354     /// </remarks>
     355     /// <param name="connection">A valid SqlConnection</param>
     356     /// <param name="spName">The name of the stored procedure</param>
     357     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     358     /// <returns>An int representing the number of rows affected by the command</returns>
     359     public static int ExecuteNonQuery(SqlConnection connection, string spName, params object[] parameterValues)
     360     {
     361       if (connection == null) throw new ArgumentNullException("connection");
     362       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     363 
     364       // If we receive parameter values, we need to figure out where they go
     365       if ((parameterValues != null) && (parameterValues.Length > 0))
     366       {
     367         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     368         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
     369 
     370         // Assign the provided values to these parameters based on parameter order
     371         AssignParameterValues(commandParameters, parameterValues);
     372 
     373         // Call the overload that takes an array of SqlParameters
     374         return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
     375       }
     376       else
     377       {
     378         // Otherwise we can just call the SP without params
     379         return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
     380       }
     381     }
     382 
     383     /// <summary>
     384     /// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlTransaction. 
     385     /// </summary>
     386     /// <remarks>
     387     /// e.g.:  
     388     ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders");
     389     /// </remarks>
     390     /// <param name="transaction">A valid SqlTransaction</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>An int representing the number of rows affected by the command</returns>
     394     public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText)
     395     {
     396       // Pass through the call providing null for the set of SqlParameters
     397       return ExecuteNonQuery(transaction, commandType, commandText, (SqlParameter[])null);
     398     }
     399 
     400     /// <summary>
     401     /// Execute a SqlCommand (that returns no resultset) against the specified SqlTransaction
     402     /// using the provided parameters.
     403     /// </summary>
     404     /// <remarks>
     405     /// e.g.:  
     406     ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     407     /// </remarks>
     408     /// <param name="transaction">A valid SqlTransaction</param>
     409     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     410     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     411     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     412     /// <returns>An int representing the number of rows affected by the command</returns>
     413     public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     414     {
     415       if (transaction == null) throw new ArgumentNullException("transaction");
     416       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
     417 
     418       // Create a command and prepare it for execution
     419       SqlCommand cmd = new SqlCommand();
     420       bool mustCloseConnection = false;
     421       PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
     422 
     423       // Finally, execute the command
     424       int retval = cmd.ExecuteNonQuery();
     425 
     426       // Detach the SqlParameters from the command object, so they can be used again
     427       cmd.Parameters.Clear();
     428       return retval;
     429     }
     430 
     431     /// <summary>
     432     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified 
     433     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
     434     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     435     /// </summary>
     436     /// <remarks>
     437     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     438     /// 
     439     /// e.g.:  
     440     ///  int result = ExecuteNonQuery(conn, trans, "PublishOrders", 24, 36);
     441     /// </remarks>
     442     /// <param name="transaction">A valid SqlTransaction</param>
     443     /// <param name="spName">The name of the stored procedure</param>
     444     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     445     /// <returns>An int representing the number of rows affected by the command</returns>
     446     public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
     447     {
     448       if (transaction == null) throw new ArgumentNullException("transaction");
     449       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
     450       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     451 
     452       // If we receive parameter values, we need to figure out where they go
     453       if ((parameterValues != null) && (parameterValues.Length > 0))
     454       {
     455         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     456         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
     457 
     458         // Assign the provided values to these parameters based on parameter order
     459         AssignParameterValues(commandParameters, parameterValues);
     460 
     461         // Call the overload that takes an array of SqlParameters
     462         return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
     463       }
     464       else
     465       {
     466         // Otherwise we can just call the SP without params
     467         return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
     468       }
     469     }
     470 
     471     #endregion ExecuteNonQuery
     472 
     473     #region ExecuteDataset
     474 
     475     /// <summary>
     476     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in 
     477     /// the connection string. 
     478     /// </summary>
     479     /// <remarks>
     480     /// e.g.:  
     481     ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders");
     482     /// </remarks>
     483     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     484     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     485     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     486     /// <returns>A dataset containing the resultset generated by the command</returns>
     487     public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText)
     488     {
     489       // Pass through the call providing null for the set of SqlParameters
     490       return ExecuteDataset(connectionString, commandType, commandText, (SqlParameter[])null);
     491     }
     492 
     493     /// <summary>
     494     /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string 
     495     /// using the provided parameters.
     496     /// </summary>
     497     /// <remarks>
     498     /// e.g.:  
     499     ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     500     /// </remarks>
     501     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     502     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     503     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     504     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     505     /// <returns>A dataset containing the resultset generated by the command</returns>
     506     public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     507     {
     508       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     509 
     510       // Create & open a SqlConnection, and dispose of it after we are done
     511       using (SqlConnection connection = new SqlConnection(connectionString))
     512       {
     513         connection.Open();
     514 
     515         // Call the overload that takes a connection in place of the connection string
     516         return ExecuteDataset(connection, commandType, commandText, commandParameters);
     517       }
     518     }
     519 
     520     /// <summary>
     521     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
     522     /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
     523     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     524     /// </summary>
     525     /// <remarks>
     526     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     527     /// 
     528     /// e.g.:  
     529     ///  DataSet ds = ExecuteDataset(connString, "GetOrders", 24, 36);
     530     /// </remarks>
     531     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     532     /// <param name="spName">The name of the stored procedure</param>
     533     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     534     /// <returns>A dataset containing the resultset generated by the command</returns>
     535     public static DataSet ExecuteDataset(string connectionString, string spName, params object[] parameterValues)
     536     {
     537       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     538       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     539 
     540       // If we receive parameter values, we need to figure out where they go
     541       if ((parameterValues != null) && (parameterValues.Length > 0))
     542       {
     543         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     544         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
     545 
     546         // Assign the provided values to these parameters based on parameter order
     547         AssignParameterValues(commandParameters, parameterValues);
     548 
     549         // Call the overload that takes an array of SqlParameters
     550         return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
     551       }
     552       else
     553       {
     554         // Otherwise we can just call the SP without params
     555         return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
     556       }
     557     }
     558 
     559     /// <summary>
     560     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
     561     /// </summary>
     562     /// <remarks>
     563     /// e.g.:  
     564     ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders");
     565     /// </remarks>
     566     /// <param name="connection">A valid SqlConnection</param>
     567     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     568     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     569     /// <returns>A dataset containing the resultset generated by the command</returns>
     570     public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText)
     571     {
     572       // Pass through the call providing null for the set of SqlParameters
     573       return ExecuteDataset(connection, commandType, commandText, (SqlParameter[])null);
     574     }
     575 
     576     /// <summary>
     577     /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
     578     /// using the provided parameters.
     579     /// </summary>
     580     /// <remarks>
     581     /// e.g.:  
     582     ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     583     /// </remarks>
     584     /// <param name="connection">A valid SqlConnection</param>
     585     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     586     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     587     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     588     /// <returns>A dataset containing the resultset generated by the command</returns>
     589     public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     590     {
     591       if (connection == null) throw new ArgumentNullException("connection");
     592 
     593       // Create a command and prepare it for execution
     594       SqlCommand cmd = new SqlCommand();
     595       bool mustCloseConnection = false;
     596       PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
     597 
     598       // Create the DataAdapter & DataSet
     599       using (SqlDataAdapter da = new SqlDataAdapter(cmd))
     600       {
     601         DataSet ds = new DataSet();
     602 
     603         // Fill the DataSet using default values for DataTable names, etc
     604         da.Fill(ds);
     605 
     606         // Detach the SqlParameters from the command object, so they can be used again
     607         cmd.Parameters.Clear();
     608 
     609         if (mustCloseConnection)
     610           connection.Close();
     611 
     612         // Return the dataset
     613         return ds;
     614       }
     615     }
     616 
     617     /// <summary>
     618     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
     619     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
     620     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     621     /// </summary>
     622     /// <remarks>
     623     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     624     /// 
     625     /// e.g.:  
     626     ///  DataSet ds = ExecuteDataset(conn, "GetOrders", 24, 36);
     627     /// </remarks>
     628     /// <param name="connection">A valid SqlConnection</param>
     629     /// <param name="spName">The name of the stored procedure</param>
     630     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     631     /// <returns>A dataset containing the resultset generated by the command</returns>
     632     public static DataSet ExecuteDataset(SqlConnection connection, string spName, params object[] parameterValues)
     633     {
     634       if (connection == null) throw new ArgumentNullException("connection");
     635       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     636 
     637       // If we receive parameter values, we need to figure out where they go
     638       if ((parameterValues != null) && (parameterValues.Length > 0))
     639       {
     640         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     641         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
     642 
     643         // Assign the provided values to these parameters based on parameter order
     644         AssignParameterValues(commandParameters, parameterValues);
     645 
     646         // Call the overload that takes an array of SqlParameters
     647         return ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
     648       }
     649       else
     650       {
     651         // Otherwise we can just call the SP without params
     652         return ExecuteDataset(connection, CommandType.StoredProcedure, spName);
     653       }
     654     }
     655 
     656     /// <summary>
     657     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
     658     /// </summary>
     659     /// <remarks>
     660     /// e.g.:  
     661     ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders");
     662     /// </remarks>
     663     /// <param name="transaction">A valid SqlTransaction</param>
     664     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     665     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     666     /// <returns>A dataset containing the resultset generated by the command</returns>
     667     public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText)
     668     {
     669       // Pass through the call providing null for the set of SqlParameters
     670       return ExecuteDataset(transaction, commandType, commandText, (SqlParameter[])null);
     671     }
     672 
     673     /// <summary>
     674     /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
     675     /// using the provided parameters.
     676     /// </summary>
     677     /// <remarks>
     678     /// e.g.:  
     679     ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     680     /// </remarks>
     681     /// <param name="transaction">A valid SqlTransaction</param>
     682     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     683     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     684     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     685     /// <returns>A dataset containing the resultset generated by the command</returns>
     686     public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     687     {
     688       if (transaction == null) throw new ArgumentNullException("transaction");
     689       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
     690 
     691       // Create a command and prepare it for execution
     692       SqlCommand cmd = new SqlCommand();
     693       bool mustCloseConnection = false;
     694       PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
     695 
     696       // Create the DataAdapter & DataSet
     697       using (SqlDataAdapter da = new SqlDataAdapter(cmd))
     698       {
     699         DataSet ds = new DataSet();
     700 
     701         // Fill the DataSet using default values for DataTable names, etc
     702         da.Fill(ds);
     703 
     704         // Detach the SqlParameters from the command object, so they can be used again
     705         cmd.Parameters.Clear();
     706 
     707         // Return the dataset
     708         return ds;
     709       }
     710     }
     711 
     712     /// <summary>
     713     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified 
     714     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
     715     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     716     /// </summary>
     717     /// <remarks>
     718     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     719     /// 
     720     /// e.g.:  
     721     ///  DataSet ds = ExecuteDataset(trans, "GetOrders", 24, 36);
     722     /// </remarks>
     723     /// <param name="transaction">A valid SqlTransaction</param>
     724     /// <param name="spName">The name of the stored procedure</param>
     725     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     726     /// <returns>A dataset containing the resultset generated by the command</returns>
     727     public static DataSet ExecuteDataset(SqlTransaction transaction, string spName, params object[] parameterValues)
     728     {
     729       if (transaction == null) throw new ArgumentNullException("transaction");
     730       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
     731       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     732 
     733       // If we receive parameter values, we need to figure out where they go
     734       if ((parameterValues != null) && (parameterValues.Length > 0))
     735       {
     736         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
     737         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
     738 
     739         // Assign the provided values to these parameters based on parameter order
     740         AssignParameterValues(commandParameters, parameterValues);
     741 
     742         // Call the overload that takes an array of SqlParameters
     743         return ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
     744       }
     745       else
     746       {
     747         // Otherwise we can just call the SP without params
     748         return ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
     749       }
     750     }
     751 
     752     #endregion ExecuteDataset
     753 
     754     #region ExecuteReader
     755 
     756     /// <summary>
     757     /// This enum is used to indicate whether the connection was provided by the caller, or created by SqlHelper, so that
     758     /// we can set the appropriate CommandBehavior when calling ExecuteReader()
     759     /// </summary>
     760     private enum SqlConnectionOwnership
     761     {
     762       /// <summary>Connection is owned and managed by SqlHelper</summary>
     763       Internal,
     764       /// <summary>Connection is owned and managed by the caller</summary>
     765       External
     766     }
     767 
     768     /// <summary>
     769     /// Create and prepare a SqlCommand, and call ExecuteReader with the appropriate CommandBehavior.
     770     /// </summary>
     771     /// <remarks>
     772     /// If we created and opened the connection, we want the connection to be closed when the DataReader is closed.
     773     /// 
     774     /// If the caller provided the connection, we want to leave it to them to manage.
     775     /// </remarks>
     776     /// <param name="connection">A valid SqlConnection, on which to execute this command</param>
     777     /// <param name="transaction">A valid SqlTransaction, or 'null'</param>
     778     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     779     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     780     /// <param name="commandParameters">An array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
     781     /// <param name="connectionOwnership">Indicates whether the connection parameter was provided by the caller, or created by SqlHelper</param>
     782     /// <returns>SqlDataReader containing the results of the command</returns>
     783     private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)
     784     {
     785       if (connection == null) throw new ArgumentNullException("connection");
     786 
     787       bool mustCloseConnection = false;
     788       // Create a command and prepare it for execution
     789       SqlCommand cmd = new SqlCommand();
     790       try
     791       {
     792         PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
     793 
     794         // Create a reader
     795         SqlDataReader dataReader;
     796 
     797         // Call ExecuteReader with the appropriate CommandBehavior
     798         if (connectionOwnership == SqlConnectionOwnership.External)
     799         {
     800           dataReader = cmd.ExecuteReader();
     801         }
     802         else
     803         {
     804           dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
     805         }
     806 
     807         // Detach the SqlParameters from the command object, so they can be used again.
     808         // HACK: There is a problem here, the output parameter values are fletched 
     809         // when the reader is closed, so if the parameters are detached from the command
     810         // then the SqlReader can愒 set its values. 
     811         // When this happen, the parameters can愒 be used again in other command.
     812         bool canClear = true;
     813         foreach (SqlParameter commandParameter in cmd.Parameters)
     814         {
     815           if (commandParameter.Direction != ParameterDirection.Input)
     816             canClear = false;
     817         }
     818 
     819         if (canClear)
     820         {
     821           cmd.Parameters.Clear();
     822         }
     823 
     824         return dataReader;
     825       }
     826       catch
     827       {
     828         if (mustCloseConnection)
     829           connection.Close();
     830         throw;
     831       }
     832     }
     833 
     834     /// <summary>
     835     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in 
     836     /// the connection string. 
     837     /// </summary>
     838     /// <remarks>
     839     /// e.g.:  
     840     ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders");
     841     /// </remarks>
     842     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     843     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     844     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     845     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     846     public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText)
     847     {
     848       // Pass through the call providing null for the set of SqlParameters
     849       return ExecuteReader(connectionString, commandType, commandText, (SqlParameter[])null);
     850     }
     851 
     852     /// <summary>
     853     /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string 
     854     /// using the provided parameters.
     855     /// </summary>
     856     /// <remarks>
     857     /// e.g.:  
     858     ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     859     /// </remarks>
     860     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     861     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     862     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     863     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     864     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     865     public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     866     {
     867       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     868       SqlConnection connection = null;
     869       try
     870       {
     871         connection = new SqlConnection(connectionString);
     872         connection.Open();
     873 
     874         // Call the private overload that takes an internally owned connection in place of the connection string
     875         return ExecuteReader(connection, null, commandType, commandText, commandParameters, SqlConnectionOwnership.Internal);
     876       }
     877       catch
     878       {
     879         // If we fail to return the SqlDatReader, we need to close the connection ourselves
     880         if (connection != null) connection.Close();
     881         throw;
     882       }
     883 
     884     }
     885 
     886     /// <summary>
     887     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
     888     /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
     889     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     890     /// </summary>
     891     /// <remarks>
     892     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     893     /// 
     894     /// e.g.:  
     895     ///  SqlDataReader dr = ExecuteReader(connString, "GetOrders", 24, 36);
     896     /// </remarks>
     897     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
     898     /// <param name="spName">The name of the stored procedure</param>
     899     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     900     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     901     public static SqlDataReader ExecuteReader(string connectionString, string spName, params object[] parameterValues)
     902     {
     903       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
     904       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     905 
     906       // If we receive parameter values, we need to figure out where they go
     907       if ((parameterValues != null) && (parameterValues.Length > 0))
     908       {
     909         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
     910 
     911         AssignParameterValues(commandParameters, parameterValues);
     912 
     913         return ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
     914       }
     915       else
     916       {
     917         // Otherwise we can just call the SP without params
     918         return ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
     919       }
     920     }
     921 
     922     /// <summary>
     923     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
     924     /// </summary>
     925     /// <remarks>
     926     /// e.g.:  
     927     ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders");
     928     /// </remarks>
     929     /// <param name="connection">A valid SqlConnection</param>
     930     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
     931     /// <param name="commandText">The stored procedure name or T-SQL command</param>
     932     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     933     public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText)
     934     {
     935       // Pass through the call providing null for the set of SqlParameters
     936       return ExecuteReader(connection, commandType, commandText, (SqlParameter[])null);
     937     }
     938 
     939     /// <summary>
     940     /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
     941     /// using the provided parameters.
     942     /// </summary>
     943     /// <remarks>
     944     /// e.g.:  
     945     ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
     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     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
     951     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     952     public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
     953     {
     954       // Pass through the call to the private overload using a null transaction value and an externally owned connection
     955       return ExecuteReader(connection, (SqlTransaction)null, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
     956     }
     957 
     958     /// <summary>
     959     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
     960     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
     961     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
     962     /// </summary>
     963     /// <remarks>
     964     /// This method provides no access to output parameters or the stored procedure's return value parameter.
     965     /// 
     966     /// e.g.:  
     967     ///  SqlDataReader dr = ExecuteReader(conn, "GetOrders", 24, 36);
     968     /// </remarks>
     969     /// <param name="connection">A valid SqlConnection</param>
     970     /// <param name="spName">The name of the stored procedure</param>
     971     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
     972     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
     973     public static SqlDataReader ExecuteReader(SqlConnection connection, string spName, params object[] parameterValues)
     974     {
     975       if (connection == null) throw new ArgumentNullException("connection");
     976       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
     977 
     978       // If we receive parameter values, we need to figure out where they go
     979       if ((parameterValues != null) && (parameterValues.Length > 0))
     980       {
     981         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
     982 
     983         AssignParameterValues(commandParameters, parameterValues);
     984 
     985         return ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
     986       }
     987       else
     988       {
     989         // Otherwise we can just call the SP without params
     990         return ExecuteReader(connection, CommandType.StoredProcedure, spName);
     991       }
     992     }
     993 
     994     /// <summary>
     995     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
     996     /// </summary>
     997     /// <remarks>
     998     /// e.g.:  
     999     ///  SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders");
    1000     /// </remarks>
    1001     /// <param name="transaction">A valid SqlTransaction</param>
    1002     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1003     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1004     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    1005     public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText)
    1006     {
    1007       // Pass through the call providing null for the set of SqlParameters
    1008       return ExecuteReader(transaction, commandType, commandText, (SqlParameter[])null);
    1009     }
    1010 
    1011     /// <summary>
    1012     /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
    1013     /// using the provided parameters.
    1014     /// </summary>
    1015     /// <remarks>
    1016     /// e.g.:  
    1017     ///   SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
    1018     /// </remarks>
    1019     /// <param name="transaction">A valid SqlTransaction</param>
    1020     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1021     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1022     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1023     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    1024     public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1025     {
    1026       if (transaction == null) throw new ArgumentNullException("transaction");
    1027       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1028 
    1029       // Pass through to private overload, indicating that the connection is owned by the caller
    1030       return ExecuteReader(transaction.Connection, transaction, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
    1031     }
    1032 
    1033     /// <summary>
    1034     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified
    1035     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
    1036     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1037     /// </summary>
    1038     /// <remarks>
    1039     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1040     /// 
    1041     /// e.g.:  
    1042     ///  SqlDataReader dr = ExecuteReader(trans, "GetOrders", 24, 36);
    1043     /// </remarks>
    1044     /// <param name="transaction">A valid SqlTransaction</param>
    1045     /// <param name="spName">The name of the stored procedure</param>
    1046     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1047     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    1048     public static SqlDataReader ExecuteReader(SqlTransaction transaction, string spName, params object[] parameterValues)
    1049     {
    1050       if (transaction == null) throw new ArgumentNullException("transaction");
    1051       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1052       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1053 
    1054       // If we receive parameter values, we need to figure out where they go
    1055       if ((parameterValues != null) && (parameterValues.Length > 0))
    1056       {
    1057         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    1058 
    1059         AssignParameterValues(commandParameters, parameterValues);
    1060 
    1061         return ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
    1062       }
    1063       else
    1064       {
    1065         // Otherwise we can just call the SP without params
    1066         return ExecuteReader(transaction, CommandType.StoredProcedure, spName);
    1067       }
    1068     }
    1069 
    1070     #endregion ExecuteReader
    1071 
    1072     #region ExecuteScalar
    1073 
    1074     /// <summary>
    1075     /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the database specified in 
    1076     /// the connection string. 
    1077     /// </summary>
    1078     /// <remarks>
    1079     /// e.g.:  
    1080     ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount");
    1081     /// </remarks>
    1082     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1083     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1084     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1085     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1086     public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText)
    1087     {
    1088       // Pass through the call providing null for the set of SqlParameters
    1089       return ExecuteScalar(connectionString, commandType, commandText, (SqlParameter[])null);
    1090     }
    1091 
    1092     /// <summary>
    1093     /// Execute a SqlCommand (that returns a 1x1 resultset) against the database specified in the connection string 
    1094     /// using the provided parameters.
    1095     /// </summary>
    1096     /// <remarks>
    1097     /// e.g.:  
    1098     ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
    1099     /// </remarks>
    1100     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1101     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1102     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1103     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1104     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1105     public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1106     {
    1107       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1108       // Create & open a SqlConnection, and dispose of it after we are done
    1109       using (SqlConnection connection = new SqlConnection(connectionString))
    1110       {
    1111         connection.Open();
    1112 
    1113         // Call the overload that takes a connection in place of the connection string
    1114         return ExecuteScalar(connection, commandType, commandText, commandParameters);
    1115       }
    1116     }
    1117 
    1118     /// <summary>
    1119     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the database specified in 
    1120     /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
    1121     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1122     /// </summary>
    1123     /// <remarks>
    1124     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1125     /// 
    1126     /// e.g.:  
    1127     ///  int orderCount = (int)ExecuteScalar(connString, "GetOrderCount", 24, 36);
    1128     /// </remarks>
    1129     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1130     /// <param name="spName">The name of the stored procedure</param>
    1131     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1132     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1133     public static object ExecuteScalar(string connectionString, string spName, params object[] parameterValues)
    1134     {
    1135       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1136       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1137 
    1138       // If we receive parameter values, we need to figure out where they go
    1139       if ((parameterValues != null) && (parameterValues.Length > 0))
    1140       {
    1141         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1142         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    1143 
    1144         // Assign the provided values to these parameters based on parameter order
    1145         AssignParameterValues(commandParameters, parameterValues);
    1146 
    1147         // Call the overload that takes an array of SqlParameters
    1148         return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
    1149       }
    1150       else
    1151       {
    1152         // Otherwise we can just call the SP without params
    1153         return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
    1154       }
    1155     }
    1156 
    1157     /// <summary>
    1158     /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlConnection. 
    1159     /// </summary>
    1160     /// <remarks>
    1161     /// e.g.:  
    1162     ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount");
    1163     /// </remarks>
    1164     /// <param name="connection">A valid SqlConnection</param>
    1165     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1166     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1167     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1168     public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText)
    1169     {
    1170       // Pass through the call providing null for the set of SqlParameters
    1171       return ExecuteScalar(connection, commandType, commandText, (SqlParameter[])null);
    1172     }
    1173 
    1174     /// <summary>
    1175     /// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection 
    1176     /// using the provided parameters.
    1177     /// </summary>
    1178     /// <remarks>
    1179     /// e.g.:  
    1180     ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
    1181     /// </remarks>
    1182     /// <param name="connection">A valid SqlConnection</param>
    1183     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1184     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1185     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1186     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1187     public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1188     {
    1189       if (connection == null) throw new ArgumentNullException("connection");
    1190 
    1191       // Create a command and prepare it for execution
    1192       SqlCommand cmd = new SqlCommand();
    1193 
    1194       bool mustCloseConnection = false;
    1195       PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    1196 
    1197       // Execute the command & return the results
    1198       object retval = cmd.ExecuteScalar();
    1199 
    1200       // Detach the SqlParameters from the command object, so they can be used again
    1201       cmd.Parameters.Clear();
    1202 
    1203       if (mustCloseConnection)
    1204         connection.Close();
    1205 
    1206       return retval;
    1207     }
    1208 
    1209     /// <summary>
    1210     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection 
    1211     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
    1212     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1213     /// </summary>
    1214     /// <remarks>
    1215     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1216     /// 
    1217     /// e.g.:  
    1218     ///  int orderCount = (int)ExecuteScalar(conn, "GetOrderCount", 24, 36);
    1219     /// </remarks>
    1220     /// <param name="connection">A valid SqlConnection</param>
    1221     /// <param name="spName">The name of the stored procedure</param>
    1222     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1223     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1224     public static object ExecuteScalar(SqlConnection connection, string spName, params object[] parameterValues)
    1225     {
    1226       if (connection == null) throw new ArgumentNullException("connection");
    1227       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1228 
    1229       // If we receive parameter values, we need to figure out where they go
    1230       if ((parameterValues != null) && (parameterValues.Length > 0))
    1231       {
    1232         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1233         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    1234 
    1235         // Assign the provided values to these parameters based on parameter order
    1236         AssignParameterValues(commandParameters, parameterValues);
    1237 
    1238         // Call the overload that takes an array of SqlParameters
    1239         return ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
    1240       }
    1241       else
    1242       {
    1243         // Otherwise we can just call the SP without params
    1244         return ExecuteScalar(connection, CommandType.StoredProcedure, spName);
    1245       }
    1246     }
    1247 
    1248     /// <summary>
    1249     /// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlTransaction. 
    1250     /// </summary>
    1251     /// <remarks>
    1252     /// e.g.:  
    1253     ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount");
    1254     /// </remarks>
    1255     /// <param name="transaction">A valid SqlTransaction</param>
    1256     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1257     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1258     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1259     public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText)
    1260     {
    1261       // Pass through the call providing null for the set of SqlParameters
    1262       return ExecuteScalar(transaction, commandType, commandText, (SqlParameter[])null);
    1263     }
    1264 
    1265     /// <summary>
    1266     /// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlTransaction
    1267     /// using the provided parameters.
    1268     /// </summary>
    1269     /// <remarks>
    1270     /// e.g.:  
    1271     ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
    1272     /// </remarks>
    1273     /// <param name="transaction">A valid SqlTransaction</param>
    1274     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1275     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1276     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1277     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1278     public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1279     {
    1280       if (transaction == null) throw new ArgumentNullException("transaction");
    1281       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1282 
    1283       // Create a command and prepare it for execution
    1284       SqlCommand cmd = new SqlCommand();
    1285       bool mustCloseConnection = false;
    1286       PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    1287 
    1288       // Execute the command & return the results
    1289       object retval = cmd.ExecuteScalar();
    1290 
    1291       // Detach the SqlParameters from the command object, so they can be used again
    1292       cmd.Parameters.Clear();
    1293       return retval;
    1294     }
    1295 
    1296     /// <summary>
    1297     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified
    1298     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
    1299     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1300     /// </summary>
    1301     /// <remarks>
    1302     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1303     /// 
    1304     /// e.g.:  
    1305     ///  int orderCount = (int)ExecuteScalar(trans, "GetOrderCount", 24, 36);
    1306     /// </remarks>
    1307     /// <param name="transaction">A valid SqlTransaction</param>
    1308     /// <param name="spName">The name of the stored procedure</param>
    1309     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1310     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    1311     public static object ExecuteScalar(SqlTransaction transaction, string spName, params object[] parameterValues)
    1312     {
    1313       if (transaction == null) throw new ArgumentNullException("transaction");
    1314       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1315       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1316 
    1317       // If we receive parameter values, we need to figure out where they go
    1318       if ((parameterValues != null) && (parameterValues.Length > 0))
    1319       {
    1320         // PPull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1321         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    1322 
    1323         // Assign the provided values to these parameters based on parameter order
    1324         AssignParameterValues(commandParameters, parameterValues);
    1325 
    1326         // Call the overload that takes an array of SqlParameters
    1327         return ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
    1328       }
    1329       else
    1330       {
    1331         // Otherwise we can just call the SP without params
    1332         return ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
    1333       }
    1334     }
    1335 
    1336     #endregion ExecuteScalar
    1337 
    1338     #region ExecuteXmlReader
    1339     /// <summary>
    1340     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
    1341     /// </summary>
    1342     /// <remarks>
    1343     /// e.g.:  
    1344     ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders");
    1345     /// </remarks>
    1346     /// <param name="connection">A valid SqlConnection</param>
    1347     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1348     /// <param name="commandText">The stored procedure name or T-SQL command using "FOR XML AUTO"</param>
    1349     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    1350     public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText)
    1351     {
    1352       // Pass through the call providing null for the set of SqlParameters
    1353       return ExecuteXmlReader(connection, commandType, commandText, (SqlParameter[])null);
    1354     }
    1355 
    1356     /// <summary>
    1357     /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
    1358     /// using the provided parameters.
    1359     /// </summary>
    1360     /// <remarks>
    1361     /// e.g.:  
    1362     ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
    1363     /// </remarks>
    1364     /// <param name="connection">A valid SqlConnection</param>
    1365     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1366     /// <param name="commandText">The stored procedure name or T-SQL command using "FOR XML AUTO"</param>
    1367     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1368     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    1369     public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1370     {
    1371       if (connection == null) throw new ArgumentNullException("connection");
    1372 
    1373       bool mustCloseConnection = false;
    1374       // Create a command and prepare it for execution
    1375       SqlCommand cmd = new SqlCommand();
    1376       try
    1377       {
    1378         PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    1379 
    1380         // Create the DataAdapter & DataSet
    1381         XmlReader retval = cmd.ExecuteXmlReader();
    1382 
    1383         // Detach the SqlParameters from the command object, so they can be used again
    1384         cmd.Parameters.Clear();
    1385 
    1386         return retval;
    1387       }
    1388       catch
    1389       {
    1390         if (mustCloseConnection)
    1391           connection.Close();
    1392         throw;
    1393       }
    1394     }
    1395 
    1396     /// <summary>
    1397     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
    1398     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
    1399     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1400     /// </summary>
    1401     /// <remarks>
    1402     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1403     /// 
    1404     /// e.g.:  
    1405     ///  XmlReader r = ExecuteXmlReader(conn, "GetOrders", 24, 36);
    1406     /// </remarks>
    1407     /// <param name="connection">A valid SqlConnection</param>
    1408     /// <param name="spName">The name of the stored procedure using "FOR XML AUTO"</param>
    1409     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1410     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    1411     public static XmlReader ExecuteXmlReader(SqlConnection connection, string spName, params object[] parameterValues)
    1412     {
    1413       if (connection == null) throw new ArgumentNullException("connection");
    1414       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1415 
    1416       // If we receive parameter values, we need to figure out where they go
    1417       if ((parameterValues != null) && (parameterValues.Length > 0))
    1418       {
    1419         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1420         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    1421 
    1422         // Assign the provided values to these parameters based on parameter order
    1423         AssignParameterValues(commandParameters, parameterValues);
    1424 
    1425         // Call the overload that takes an array of SqlParameters
    1426         return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
    1427       }
    1428       else
    1429       {
    1430         // Otherwise we can just call the SP without params
    1431         return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
    1432       }
    1433     }
    1434 
    1435     /// <summary>
    1436     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
    1437     /// </summary>
    1438     /// <remarks>
    1439     /// e.g.:  
    1440     ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders");
    1441     /// </remarks>
    1442     /// <param name="transaction">A valid SqlTransaction</param>
    1443     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1444     /// <param name="commandText">The stored procedure name or T-SQL command using "FOR XML AUTO"</param>
    1445     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    1446     public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText)
    1447     {
    1448       // Pass through the call providing null for the set of SqlParameters
    1449       return ExecuteXmlReader(transaction, commandType, commandText, (SqlParameter[])null);
    1450     }
    1451 
    1452     /// <summary>
    1453     /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
    1454     /// using the provided parameters.
    1455     /// </summary>
    1456     /// <remarks>
    1457     /// e.g.:  
    1458     ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
    1459     /// </remarks>
    1460     /// <param name="transaction">A valid SqlTransaction</param>
    1461     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1462     /// <param name="commandText">The stored procedure name or T-SQL command using "FOR XML AUTO"</param>
    1463     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1464     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    1465     public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
    1466     {
    1467       if (transaction == null) throw new ArgumentNullException("transaction");
    1468       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1469 
    1470       // Create a command and prepare it for execution
    1471       SqlCommand cmd = new SqlCommand();
    1472       bool mustCloseConnection = false;
    1473       PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    1474 
    1475       // Create the DataAdapter & DataSet
    1476       XmlReader retval = cmd.ExecuteXmlReader();
    1477 
    1478       // Detach the SqlParameters from the command object, so they can be used again
    1479       cmd.Parameters.Clear();
    1480       return retval;
    1481     }
    1482 
    1483     /// <summary>
    1484     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified 
    1485     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
    1486     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1487     /// </summary>
    1488     /// <remarks>
    1489     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1490     /// 
    1491     /// e.g.:  
    1492     ///  XmlReader r = ExecuteXmlReader(trans, "GetOrders", 24, 36);
    1493     /// </remarks>
    1494     /// <param name="transaction">A valid SqlTransaction</param>
    1495     /// <param name="spName">The name of the stored procedure</param>
    1496     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1497     /// <returns>A dataset containing the resultset generated by the command</returns>
    1498     public static XmlReader ExecuteXmlReader(SqlTransaction transaction, string spName, params object[] parameterValues)
    1499     {
    1500       if (transaction == null) throw new ArgumentNullException("transaction");
    1501       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1502       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1503 
    1504       // If we receive parameter values, we need to figure out where they go
    1505       if ((parameterValues != null) && (parameterValues.Length > 0))
    1506       {
    1507         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1508         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    1509 
    1510         // Assign the provided values to these parameters based on parameter order
    1511         AssignParameterValues(commandParameters, parameterValues);
    1512 
    1513         // Call the overload that takes an array of SqlParameters
    1514         return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
    1515       }
    1516       else
    1517       {
    1518         // Otherwise we can just call the SP without params
    1519         return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
    1520       }
    1521     }
    1522 
    1523     #endregion ExecuteXmlReader
    1524 
    1525     #region FillDataset
    1526     /// <summary>
    1527     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in 
    1528     /// the connection string. 
    1529     /// </summary>
    1530     /// <remarks>
    1531     /// e.g.:  
    1532     ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});
    1533     /// </remarks>
    1534     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1535     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1536     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1537     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1538     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1539     /// by a user defined name (probably the actual table name)</param>
    1540     public static void FillDataset(string connectionString, CommandType commandType, string commandText, DataSet dataSet, string[] tableNames)
    1541     {
    1542       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1543       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1544 
    1545       // Create & open a SqlConnection, and dispose of it after we are done
    1546       using (SqlConnection connection = new SqlConnection(connectionString))
    1547       {
    1548         connection.Open();
    1549 
    1550         // Call the overload that takes a connection in place of the connection string
    1551         FillDataset(connection, commandType, commandText, dataSet, tableNames);
    1552       }
    1553     }
    1554 
    1555     /// <summary>
    1556     /// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string 
    1557     /// using the provided parameters.
    1558     /// </summary>
    1559     /// <remarks>
    1560     /// e.g.:  
    1561     ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));
    1562     /// </remarks>
    1563     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1564     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1565     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1566     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1567     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1568     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1569     /// by a user defined name (probably the actual table name)
    1570     /// </param>
    1571     public static void FillDataset(string connectionString, CommandType commandType,
    1572         string commandText, DataSet dataSet, string[] tableNames,
    1573         params SqlParameter[] commandParameters)
    1574     {
    1575       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1576       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1577       // Create & open a SqlConnection, and dispose of it after we are done
    1578       using (SqlConnection connection = new SqlConnection(connectionString))
    1579       {
    1580         connection.Open();
    1581 
    1582         // Call the overload that takes a connection in place of the connection string
    1583         FillDataset(connection, commandType, commandText, dataSet, tableNames, commandParameters);
    1584       }
    1585     }
    1586 
    1587     /// <summary>
    1588     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
    1589     /// the connection string using the provided parameter values.  This method will query the database to discover the parameters for the 
    1590     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1591     /// </summary>
    1592     /// <remarks>
    1593     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1594     /// 
    1595     /// e.g.:  
    1596     ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, 24);
    1597     /// </remarks>
    1598     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1599     /// <param name="spName">The name of the stored procedure</param>
    1600     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1601     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1602     /// by a user defined name (probably the actual table name)
    1603     /// </param>    
    1604     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1605     public static void FillDataset(string connectionString, string spName,
    1606         DataSet dataSet, string[] tableNames,
    1607         params object[] parameterValues)
    1608     {
    1609       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1610       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1611       // Create & open a SqlConnection, and dispose of it after we are done
    1612       using (SqlConnection connection = new SqlConnection(connectionString))
    1613       {
    1614         connection.Open();
    1615 
    1616         // Call the overload that takes a connection in place of the connection string
    1617         FillDataset(connection, spName, dataSet, tableNames, parameterValues);
    1618       }
    1619     }
    1620 
    1621     /// <summary>
    1622     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection. 
    1623     /// </summary>
    1624     /// <remarks>
    1625     /// e.g.:  
    1626     ///  FillDataset(conn, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});
    1627     /// </remarks>
    1628     /// <param name="connection">A valid SqlConnection</param>
    1629     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1630     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1631     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1632     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1633     /// by a user defined name (probably the actual table name)
    1634     /// </param>    
    1635     public static void FillDataset(SqlConnection connection, CommandType commandType,
    1636         string commandText, DataSet dataSet, string[] tableNames)
    1637     {
    1638       FillDataset(connection, commandType, commandText, dataSet, tableNames, null);
    1639     }
    1640 
    1641     /// <summary>
    1642     /// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection 
    1643     /// using the provided parameters.
    1644     /// </summary>
    1645     /// <remarks>
    1646     /// e.g.:  
    1647     ///  FillDataset(conn, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));
    1648     /// </remarks>
    1649     /// <param name="connection">A valid SqlConnection</param>
    1650     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1651     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1652     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1653     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1654     /// by a user defined name (probably the actual table name)
    1655     /// </param>
    1656     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1657     public static void FillDataset(SqlConnection connection, CommandType commandType,
    1658         string commandText, DataSet dataSet, string[] tableNames,
    1659         params SqlParameter[] commandParameters)
    1660     {
    1661       FillDataset(connection, null, commandType, commandText, dataSet, tableNames, commandParameters);
    1662     }
    1663 
    1664     /// <summary>
    1665     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
    1666     /// using the provided parameter values.  This method will query the database to discover the parameters for the 
    1667     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1668     /// </summary>
    1669     /// <remarks>
    1670     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1671     /// 
    1672     /// e.g.:  
    1673     ///  FillDataset(conn, "GetOrders", ds, new string[] {"orders"}, 24, 36);
    1674     /// </remarks>
    1675     /// <param name="connection">A valid SqlConnection</param>
    1676     /// <param name="spName">The name of the stored procedure</param>
    1677     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1678     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1679     /// by a user defined name (probably the actual table name)
    1680     /// </param>
    1681     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1682     public static void FillDataset(SqlConnection connection, string spName,
    1683         DataSet dataSet, string[] tableNames,
    1684         params object[] parameterValues)
    1685     {
    1686       if (connection == null) throw new ArgumentNullException("connection");
    1687       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1688       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1689 
    1690       // If we receive parameter values, we need to figure out where they go
    1691       if ((parameterValues != null) && (parameterValues.Length > 0))
    1692       {
    1693         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1694         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    1695 
    1696         // Assign the provided values to these parameters based on parameter order
    1697         AssignParameterValues(commandParameters, parameterValues);
    1698 
    1699         // Call the overload that takes an array of SqlParameters
    1700         FillDataset(connection, CommandType.StoredProcedure, spName, dataSet, tableNames, commandParameters);
    1701       }
    1702       else
    1703       {
    1704         // Otherwise we can just call the SP without params
    1705         FillDataset(connection, CommandType.StoredProcedure, spName, dataSet, tableNames);
    1706       }
    1707     }
    1708 
    1709     /// <summary>
    1710     /// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction. 
    1711     /// </summary>
    1712     /// <remarks>
    1713     /// e.g.:  
    1714     ///  FillDataset(trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});
    1715     /// </remarks>
    1716     /// <param name="transaction">A valid SqlTransaction</param>
    1717     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1718     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1719     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1720     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1721     /// by a user defined name (probably the actual table name)
    1722     /// </param>
    1723     public static void FillDataset(SqlTransaction transaction, CommandType commandType,
    1724         string commandText,
    1725         DataSet dataSet, string[] tableNames)
    1726     {
    1727       FillDataset(transaction, commandType, commandText, dataSet, tableNames, null);
    1728     }
    1729 
    1730     /// <summary>
    1731     /// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
    1732     /// using the provided parameters.
    1733     /// </summary>
    1734     /// <remarks>
    1735     /// e.g.:  
    1736     ///  FillDataset(trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));
    1737     /// </remarks>
    1738     /// <param name="transaction">A valid SqlTransaction</param>
    1739     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1740     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1741     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1742     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1743     /// by a user defined name (probably the actual table name)
    1744     /// </param>
    1745     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1746     public static void FillDataset(SqlTransaction transaction, CommandType commandType,
    1747         string commandText, DataSet dataSet, string[] tableNames,
    1748         params SqlParameter[] commandParameters)
    1749     {
    1750       FillDataset(transaction.Connection, transaction, commandType, commandText, dataSet, tableNames, commandParameters);
    1751     }
    1752 
    1753     /// <summary>
    1754     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified 
    1755     /// SqlTransaction using the provided parameter values.  This method will query the database to discover the parameters for the 
    1756     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    1757     /// </summary>
    1758     /// <remarks>
    1759     /// This method provides no access to output parameters or the stored procedure's return value parameter.
    1760     /// 
    1761     /// e.g.:  
    1762     ///  FillDataset(trans, "GetOrders", ds, new string[]{"orders"}, 24, 36);
    1763     /// </remarks>
    1764     /// <param name="transaction">A valid SqlTransaction</param>
    1765     /// <param name="spName">The name of the stored procedure</param>
    1766     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1767     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1768     /// by a user defined name (probably the actual table name)
    1769     /// </param>
    1770     /// <param name="parameterValues">An array of objects to be assigned as the input values of the stored procedure</param>
    1771     public static void FillDataset(SqlTransaction transaction, string spName,
    1772         DataSet dataSet, string[] tableNames,
    1773         params object[] parameterValues)
    1774     {
    1775       if (transaction == null) throw new ArgumentNullException("transaction");
    1776       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    1777       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1778       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1779 
    1780       // If we receive parameter values, we need to figure out where they go
    1781       if ((parameterValues != null) && (parameterValues.Length > 0))
    1782       {
    1783         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1784         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    1785 
    1786         // Assign the provided values to these parameters based on parameter order
    1787         AssignParameterValues(commandParameters, parameterValues);
    1788 
    1789         // Call the overload that takes an array of SqlParameters
    1790         FillDataset(transaction, CommandType.StoredProcedure, spName, dataSet, tableNames, commandParameters);
    1791       }
    1792       else
    1793       {
    1794         // Otherwise we can just call the SP without params
    1795         FillDataset(transaction, CommandType.StoredProcedure, spName, dataSet, tableNames);
    1796       }
    1797     }
    1798 
    1799     /// <summary>
    1800     /// Private helper method that execute a SqlCommand (that returns a resultset) against the specified SqlTransaction and SqlConnection
    1801     /// using the provided parameters.
    1802     /// </summary>
    1803     /// <remarks>
    1804     /// e.g.:  
    1805     ///  FillDataset(conn, trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));
    1806     /// </remarks>
    1807     /// <param name="connection">A valid SqlConnection</param>
    1808     /// <param name="transaction">A valid SqlTransaction</param>
    1809     /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    1810     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    1811     /// <param name="dataSet">A dataset wich will contain the resultset generated by the command</param>
    1812     /// <param name="tableNames">This array will be used to create table mappings allowing the DataTables to be referenced
    1813     /// by a user defined name (probably the actual table name)
    1814     /// </param>
    1815     /// <param name="commandParameters">An array of SqlParamters used to execute the command</param>
    1816     private static void FillDataset(SqlConnection connection, SqlTransaction transaction, CommandType commandType,
    1817       string commandText, DataSet dataSet, string[] tableNames,
    1818       params SqlParameter[] commandParameters)
    1819     {
    1820       if (connection == null) throw new ArgumentNullException("connection");
    1821       if (dataSet == null) throw new ArgumentNullException("dataSet");
    1822 
    1823       // Create a command and prepare it for execution
    1824       SqlCommand command = new SqlCommand();
    1825       bool mustCloseConnection = false;
    1826       PrepareCommand(command, connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    1827 
    1828       // Create the DataAdapter & DataSet
    1829       using (SqlDataAdapter dataAdapter = new SqlDataAdapter(command))
    1830       {
    1831 
    1832         // Add the table mappings specified by the user
    1833         if (tableNames != null && tableNames.Length > 0)
    1834         {
    1835           string tableName = "Table";
    1836           for (int index = 0; index < tableNames.Length; index++)
    1837           {
    1838             if (tableNames[index] == null || tableNames[index].Length == 0) throw new ArgumentException("The tableNames parameter must contain a list of tables, a value was provided as null or empty string.", "tableNames");
    1839             dataAdapter.TableMappings.Add(tableName, tableNames[index]);
    1840             tableName += (index + 1).ToString();
    1841           }
    1842         }
    1843 
    1844         // Fill the DataSet using default values for DataTable names, etc
    1845         dataAdapter.Fill(dataSet);
    1846 
    1847         // Detach the SqlParameters from the command object, so they can be used again
    1848         command.Parameters.Clear();
    1849       }
    1850 
    1851       if (mustCloseConnection)
    1852         connection.Close();
    1853     }
    1854     #endregion
    1855 
    1856     #region UpdateDataset
    1857     /// <summary>
    1858     /// Executes the respective command for each inserted, updated, or deleted row in the DataSet.
    1859     /// </summary>
    1860     /// <remarks>
    1861     /// e.g.:  
    1862     ///  UpdateDataset(conn, insertCommand, deleteCommand, updateCommand, dataSet, "Order");
    1863     /// </remarks>
    1864     /// <param name="insertCommand">A valid transact-SQL statement or stored procedure to insert new records into the data source</param>
    1865     /// <param name="deleteCommand">A valid transact-SQL statement or stored procedure to delete records from the data source</param>
    1866     /// <param name="updateCommand">A valid transact-SQL statement or stored procedure used to update records in the data source</param>
    1867     /// <param name="dataSet">The DataSet used to update the data source</param>
    1868     /// <param name="tableName">The DataTable used to update the data source.</param>
    1869     public static void UpdateDataset(SqlCommand insertCommand, SqlCommand deleteCommand, SqlCommand updateCommand, DataSet dataSet, string tableName)
    1870     {
    1871       if (insertCommand == null) throw new ArgumentNullException("insertCommand");
    1872       if (deleteCommand == null) throw new ArgumentNullException("deleteCommand");
    1873       if (updateCommand == null) throw new ArgumentNullException("updateCommand");
    1874       if (tableName == null || tableName.Length == 0) throw new ArgumentNullException("tableName");
    1875 
    1876       // Create a SqlDataAdapter, and dispose of it after we are done
    1877       using (SqlDataAdapter dataAdapter = new SqlDataAdapter())
    1878       {
    1879         // Set the data adapter commands
    1880         dataAdapter.UpdateCommand = updateCommand;
    1881         dataAdapter.InsertCommand = insertCommand;
    1882         dataAdapter.DeleteCommand = deleteCommand;
    1883 
    1884         // Update the dataset changes in the data source
    1885         dataAdapter.Update(dataSet, tableName);
    1886 
    1887         // Commit all the changes made to the DataSet
    1888         dataSet.AcceptChanges();
    1889       }
    1890     }
    1891     #endregion
    1892 
    1893     #region CreateCommand
    1894     /// <summary>
    1895     /// Simplify the creation of a Sql command object by allowing
    1896     /// a stored procedure and optional parameters to be provided
    1897     /// </summary>
    1898     /// <remarks>
    1899     /// e.g.:  
    1900     ///  SqlCommand command = CreateCommand(conn, "AddCustomer", "CustomerID", "CustomerName");
    1901     /// </remarks>
    1902     /// <param name="connection">A valid SqlConnection object</param>
    1903     /// <param name="spName">The name of the stored procedure</param>
    1904     /// <param name="sourceColumns">An array of string to be assigned as the source columns of the stored procedure parameters</param>
    1905     /// <returns>A valid SqlCommand object</returns>
    1906     public static SqlCommand CreateCommand(SqlConnection connection, string spName, params string[] sourceColumns)
    1907     {
    1908       if (connection == null) throw new ArgumentNullException("connection");
    1909       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1910 
    1911       // Create a SqlCommand
    1912       SqlCommand cmd = new SqlCommand(spName, connection);
    1913       cmd.CommandType = CommandType.StoredProcedure;
    1914 
    1915       // If we receive parameter values, we need to figure out where they go
    1916       if ((sourceColumns != null) && (sourceColumns.Length > 0))
    1917       {
    1918         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1919         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    1920 
    1921         // Assign the provided source columns to these parameters based on parameter order
    1922         for (int index = 0; index < sourceColumns.Length; index++)
    1923           commandParameters[index].SourceColumn = sourceColumns[index];
    1924 
    1925         // Attach the discovered parameters to the SqlCommand object
    1926         AttachParameters(cmd, commandParameters);
    1927       }
    1928 
    1929       return cmd;
    1930     }
    1931     #endregion
    1932 
    1933     #region ExecuteNonQueryTypedParams
    1934     /// <summary>
    1935     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the database specified in 
    1936     /// the connection string using the dataRow column values as the stored procedure's parameters values.
    1937     /// This method will query the database to discover the parameters for the 
    1938     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    1939     /// </summary>
    1940     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    1941     /// <param name="spName">The name of the stored procedure</param>
    1942     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    1943     /// <returns>An int representing the number of rows affected by the command</returns>
    1944     public static int ExecuteNonQueryTypedParams(String connectionString, String spName, DataRow dataRow)
    1945     {
    1946       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    1947       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1948 
    1949       // If the row has values, the store procedure parameters must be initialized
    1950       if (dataRow != null && dataRow.ItemArray.Length > 0)
    1951       {
    1952         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1953         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    1954 
    1955         // Set the parameters values
    1956         AssignParameterValues(commandParameters, dataRow);
    1957 
    1958         return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
    1959       }
    1960       else
    1961       {
    1962         return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
    1963       }
    1964     }
    1965 
    1966     /// <summary>
    1967     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified SqlConnection 
    1968     /// using the dataRow column values as the stored procedure's parameters values.  
    1969     /// This method will query the database to discover the parameters for the 
    1970     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    1971     /// </summary>
    1972     /// <param name="connection">A valid SqlConnection object</param>
    1973     /// <param name="spName">The name of the stored procedure</param>
    1974     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    1975     /// <returns>An int representing the number of rows affected by the command</returns>
    1976     public static int ExecuteNonQueryTypedParams(SqlConnection connection, String spName, DataRow dataRow)
    1977     {
    1978       if (connection == null) throw new ArgumentNullException("connection");
    1979       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    1980 
    1981       // If the row has values, the store procedure parameters must be initialized
    1982       if (dataRow != null && dataRow.ItemArray.Length > 0)
    1983       {
    1984         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    1985         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    1986 
    1987         // Set the parameters values
    1988         AssignParameterValues(commandParameters, dataRow);
    1989 
    1990         return SqlHelper.ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
    1991       }
    1992       else
    1993       {
    1994         return SqlHelper.ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
    1995       }
    1996     }
    1997 
    1998     /// <summary>
    1999     /// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified
    2000     /// SqlTransaction using the dataRow column values as the stored procedure's parameters values.
    2001     /// This method will query the database to discover the parameters for the 
    2002     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    2003     /// </summary>
    2004     /// <param name="transaction">A valid SqlTransaction object</param>
    2005     /// <param name="spName">The name of the stored procedure</param>
    2006     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2007     /// <returns>An int representing the number of rows affected by the command</returns>
    2008     public static int ExecuteNonQueryTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
    2009     {
    2010       if (transaction == null) throw new ArgumentNullException("transaction");
    2011       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    2012       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2013 
    2014       // Sf the row has values, the store procedure parameters must be initialized
    2015       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2016       {
    2017         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2018         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    2019 
    2020         // Set the parameters values
    2021         AssignParameterValues(commandParameters, dataRow);
    2022 
    2023         return SqlHelper.ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
    2024       }
    2025       else
    2026       {
    2027         return SqlHelper.ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
    2028       }
    2029     }
    2030     #endregion
    2031 
    2032     #region ExecuteDatasetTypedParams
    2033     /// <summary>
    2034     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
    2035     /// the connection string using the dataRow column values as the stored procedure's parameters values.
    2036     /// This method will query the database to discover the parameters for the 
    2037     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    2038     /// </summary>
    2039     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2040     /// <param name="spName">The name of the stored procedure</param>
    2041     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2042     /// <returns>A dataset containing the resultset generated by the command</returns>
    2043     public static DataSet ExecuteDatasetTypedParams(string connectionString, String spName, DataRow dataRow)
    2044     {
    2045       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2046       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2047 
    2048       //If the row has values, the store procedure parameters must be initialized
    2049       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2050       {
    2051         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2052         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    2053 
    2054         // Set the parameters values
    2055         AssignParameterValues(commandParameters, dataRow);
    2056 
    2057         return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
    2058       }
    2059       else
    2060       {
    2061         return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
    2062       }
    2063     }
    2064 
    2065     /// <summary>
    2066     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
    2067     /// using the dataRow column values as the store procedure's parameters values.
    2068     /// This method will query the database to discover the parameters for the 
    2069     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    2070     /// </summary>
    2071     /// <param name="connection">A valid SqlConnection object</param>
    2072     /// <param name="spName">The name of the stored procedure</param>
    2073     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2074     /// <returns>A dataset containing the resultset generated by the command</returns>
    2075     public static DataSet ExecuteDatasetTypedParams(SqlConnection connection, String spName, DataRow dataRow)
    2076     {
    2077       if (connection == null) throw new ArgumentNullException("connection");
    2078       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2079 
    2080       // If the row has values, the store procedure parameters must be initialized
    2081       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2082       {
    2083         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2084         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    2085 
    2086         // Set the parameters values
    2087         AssignParameterValues(commandParameters, dataRow);
    2088 
    2089         return SqlHelper.ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
    2090       }
    2091       else
    2092       {
    2093         return SqlHelper.ExecuteDataset(connection, CommandType.StoredProcedure, spName);
    2094       }
    2095     }
    2096 
    2097     /// <summary>
    2098     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlTransaction 
    2099     /// using the dataRow column values as the stored procedure's parameters values.
    2100     /// This method will query the database to discover the parameters for the 
    2101     /// stored procedure (the first time each stored procedure is called), and assign the values based on row values.
    2102     /// </summary>
    2103     /// <param name="transaction">A valid SqlTransaction object</param>
    2104     /// <param name="spName">The name of the stored procedure</param>
    2105     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2106     /// <returns>A dataset containing the resultset generated by the command</returns>
    2107     public static DataSet ExecuteDatasetTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
    2108     {
    2109       if (transaction == null) throw new ArgumentNullException("transaction");
    2110       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    2111       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2112 
    2113       // If the row has values, the store procedure parameters must be initialized
    2114       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2115       {
    2116         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2117         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    2118 
    2119         // Set the parameters values
    2120         AssignParameterValues(commandParameters, dataRow);
    2121 
    2122         return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
    2123       }
    2124       else
    2125       {
    2126         return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
    2127       }
    2128     }
    2129 
    2130     #endregion
    2131 
    2132     #region ExecuteReaderTypedParams
    2133     /// <summary>
    2134     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in 
    2135     /// the connection string using the dataRow column values as the stored procedure's parameters values.
    2136     /// This method will query the database to discover the parameters for the 
    2137     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2138     /// </summary>
    2139     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2140     /// <param name="spName">The name of the stored procedure</param>
    2141     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2142     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    2143     public static SqlDataReader ExecuteReaderTypedParams(String connectionString, String spName, DataRow dataRow)
    2144     {
    2145       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2146       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2147 
    2148       // If the row has values, the store procedure parameters must be initialized
    2149       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2150       {
    2151         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2152         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    2153 
    2154         // Set the parameters values
    2155         AssignParameterValues(commandParameters, dataRow);
    2156 
    2157         return SqlHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
    2158       }
    2159       else
    2160       {
    2161         return SqlHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
    2162       }
    2163     }
    2164 
    2165 
    2166     /// <summary>
    2167     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
    2168     /// using the dataRow column values as the stored procedure's parameters values.
    2169     /// This method will query the database to discover the parameters for the 
    2170     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2171     /// </summary>
    2172     /// <param name="connection">A valid SqlConnection object</param>
    2173     /// <param name="spName">The name of the stored procedure</param>
    2174     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2175     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    2176     public static SqlDataReader ExecuteReaderTypedParams(SqlConnection connection, String spName, DataRow dataRow)
    2177     {
    2178       if (connection == null) throw new ArgumentNullException("connection");
    2179       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2180 
    2181       // If the row has values, the store procedure parameters must be initialized
    2182       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2183       {
    2184         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2185         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    2186 
    2187         // Set the parameters values
    2188         AssignParameterValues(commandParameters, dataRow);
    2189 
    2190         return SqlHelper.ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
    2191       }
    2192       else
    2193       {
    2194         return SqlHelper.ExecuteReader(connection, CommandType.StoredProcedure, spName);
    2195       }
    2196     }
    2197 
    2198     /// <summary>
    2199     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlTransaction 
    2200     /// using the dataRow column values as the stored procedure's parameters values.
    2201     /// This method will query the database to discover the parameters for the 
    2202     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2203     /// </summary>
    2204     /// <param name="transaction">A valid SqlTransaction object</param>
    2205     /// <param name="spName">The name of the stored procedure</param>
    2206     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2207     /// <returns>A SqlDataReader containing the resultset generated by the command</returns>
    2208     public static SqlDataReader ExecuteReaderTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
    2209     {
    2210       if (transaction == null) throw new ArgumentNullException("transaction");
    2211       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    2212       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2213 
    2214       // If the row has values, the store procedure parameters must be initialized
    2215       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2216       {
    2217         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2218         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    2219 
    2220         // Set the parameters values
    2221         AssignParameterValues(commandParameters, dataRow);
    2222 
    2223         return SqlHelper.ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
    2224       }
    2225       else
    2226       {
    2227         return SqlHelper.ExecuteReader(transaction, CommandType.StoredProcedure, spName);
    2228       }
    2229     }
    2230     #endregion
    2231 
    2232     #region ExecuteScalarTypedParams
    2233     /// <summary>
    2234     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the database specified in 
    2235     /// the connection string using the dataRow column values as the stored procedure's parameters values.
    2236     /// This method will query the database to discover the parameters for the 
    2237     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2238     /// </summary>
    2239     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2240     /// <param name="spName">The name of the stored procedure</param>
    2241     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2242     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    2243     public static object ExecuteScalarTypedParams(String connectionString, String spName, DataRow dataRow)
    2244     {
    2245       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2246       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2247 
    2248       // If the row has values, the store procedure parameters must be initialized
    2249       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2250       {
    2251         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2252         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    2253 
    2254         // Set the parameters values
    2255         AssignParameterValues(commandParameters, dataRow);
    2256 
    2257         return SqlHelper.ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
    2258       }
    2259       else
    2260       {
    2261         return SqlHelper.ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
    2262       }
    2263     }
    2264 
    2265     /// <summary>
    2266     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection 
    2267     /// using the dataRow column values as the stored procedure's parameters values.
    2268     /// This method will query the database to discover the parameters for the 
    2269     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2270     /// </summary>
    2271     /// <param name="connection">A valid SqlConnection object</param>
    2272     /// <param name="spName">The name of the stored procedure</param>
    2273     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2274     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    2275     public static object ExecuteScalarTypedParams(SqlConnection connection, String spName, DataRow dataRow)
    2276     {
    2277       if (connection == null) throw new ArgumentNullException("connection");
    2278       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2279 
    2280       // If the row has values, the store procedure parameters must be initialized
    2281       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2282       {
    2283         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2284         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    2285 
    2286         // Set the parameters values
    2287         AssignParameterValues(commandParameters, dataRow);
    2288 
    2289         return SqlHelper.ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
    2290       }
    2291       else
    2292       {
    2293         return SqlHelper.ExecuteScalar(connection, CommandType.StoredProcedure, spName);
    2294       }
    2295     }
    2296 
    2297     /// <summary>
    2298     /// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified SqlTransaction
    2299     /// using the dataRow column values as the stored procedure's parameters values.
    2300     /// This method will query the database to discover the parameters for the 
    2301     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2302     /// </summary>
    2303     /// <param name="transaction">A valid SqlTransaction object</param>
    2304     /// <param name="spName">The name of the stored procedure</param>
    2305     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2306     /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    2307     public static object ExecuteScalarTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
    2308     {
    2309       if (transaction == null) throw new ArgumentNullException("transaction");
    2310       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    2311       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2312 
    2313       // If the row has values, the store procedure parameters must be initialized
    2314       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2315       {
    2316         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2317         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    2318 
    2319         // Set the parameters values
    2320         AssignParameterValues(commandParameters, dataRow);
    2321 
    2322         return SqlHelper.ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
    2323       }
    2324       else
    2325       {
    2326         return SqlHelper.ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
    2327       }
    2328     }
    2329     #endregion
    2330 
    2331     #region ExecuteXmlReaderTypedParams
    2332     /// <summary>
    2333     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection 
    2334     /// using the dataRow column values as the stored procedure's parameters values.
    2335     /// This method will query the database to discover the parameters for the 
    2336     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2337     /// </summary>
    2338     /// <param name="connection">A valid SqlConnection object</param>
    2339     /// <param name="spName">The name of the stored procedure</param>
    2340     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2341     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    2342     public static XmlReader ExecuteXmlReaderTypedParams(SqlConnection connection, String spName, DataRow dataRow)
    2343     {
    2344       if (connection == null) throw new ArgumentNullException("connection");
    2345       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2346 
    2347       // If the row has values, the store procedure parameters must be initialized
    2348       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2349       {
    2350         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2351         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    2352 
    2353         // Set the parameters values
    2354         AssignParameterValues(commandParameters, dataRow);
    2355 
    2356         return SqlHelper.ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
    2357       }
    2358       else
    2359       {
    2360         return SqlHelper.ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
    2361       }
    2362     }
    2363 
    2364     /// <summary>
    2365     /// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlTransaction 
    2366     /// using the dataRow column values as the stored procedure's parameters values.
    2367     /// This method will query the database to discover the parameters for the 
    2368     /// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
    2369     /// </summary>
    2370     /// <param name="transaction">A valid SqlTransaction object</param>
    2371     /// <param name="spName">The name of the stored procedure</param>
    2372     /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values.</param>
    2373     /// <returns>An XmlReader containing the resultset generated by the command</returns>
    2374     public static XmlReader ExecuteXmlReaderTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
    2375     {
    2376       if (transaction == null) throw new ArgumentNullException("transaction");
    2377       if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    2378       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2379 
    2380       // If the row has values, the store procedure parameters must be initialized
    2381       if (dataRow != null && dataRow.ItemArray.Length > 0)
    2382       {
    2383         // Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
    2384         SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    2385 
    2386         // Set the parameters values
    2387         AssignParameterValues(commandParameters, dataRow);
    2388 
    2389         return SqlHelper.ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
    2390       }
    2391       else
    2392       {
    2393         return SqlHelper.ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
    2394       }
    2395     }
    2396     #endregion
    2397 
    2398   }
    2399 
    2400   /// <summary>
    2401   /// SqlHelperParameterCache provides functions to leverage a static cache of procedure parameters, and the
    2402   /// ability to discover parameters for stored procedures at run-time.
    2403   /// </summary>
    2404   public sealed class SqlHelperParameterCache
    2405   {
    2406     #region private methods, variables, and constructors
    2407 
    2408     //Since this class provides only static methods, make the default constructor private to prevent 
    2409     //instances from being created with "new SqlHelperParameterCache()"
    2410     private SqlHelperParameterCache() { }
    2411 
    2412     private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
    2413 
    2414     /// <summary>
    2415     /// Resolve at run time the appropriate set of SqlParameters for a stored procedure
    2416     /// </summary>
    2417     /// <param name="connection">A valid SqlConnection object</param>
    2418     /// <param name="spName">The name of the stored procedure</param>
    2419     /// <param name="includeReturnValueParameter">Whether or not to include their return value parameter</param>
    2420     /// <returns>The parameter array discovered.</returns>
    2421     private static SqlParameter[] DiscoverSpParameterSet(SqlConnection connection, string spName, bool includeReturnValueParameter)
    2422     {
    2423       if (connection == null) throw new ArgumentNullException("connection");
    2424       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2425 
    2426       SqlCommand cmd = new SqlCommand(spName, connection);
    2427       cmd.CommandType = CommandType.StoredProcedure;
    2428 
    2429       connection.Open();
    2430       SqlCommandBuilder.DeriveParameters(cmd);
    2431       connection.Close();
    2432 
    2433       if (!includeReturnValueParameter)
    2434       {
    2435         cmd.Parameters.RemoveAt(0);
    2436       }
    2437 
    2438       SqlParameter[] discoveredParameters = new SqlParameter[cmd.Parameters.Count];
    2439 
    2440       cmd.Parameters.CopyTo(discoveredParameters, 0);
    2441 
    2442       // Init the parameters with a DBNull value
    2443       foreach (SqlParameter discoveredParameter in discoveredParameters)
    2444       {
    2445         discoveredParameter.Value = DBNull.Value;
    2446       }
    2447       return discoveredParameters;
    2448     }
    2449 
    2450     /// <summary>
    2451     /// Deep copy of cached SqlParameter array
    2452     /// </summary>
    2453     /// <param name="originalParameters"></param>
    2454     /// <returns></returns>
    2455     private static SqlParameter[] CloneParameters(SqlParameter[] originalParameters)
    2456     {
    2457       SqlParameter[] clonedParameters = new SqlParameter[originalParameters.Length];
    2458 
    2459       for (int i = 0, j = originalParameters.Length; i < j; i++)
    2460       {
    2461         clonedParameters[i] = (SqlParameter)((ICloneable)originalParameters[i]).Clone();
    2462       }
    2463 
    2464       return clonedParameters;
    2465     }
    2466 
    2467     #endregion private methods, variables, and constructors
    2468 
    2469     #region caching functions
    2470 
    2471     /// <summary>
    2472     /// Add parameter array to the cache
    2473     /// </summary>
    2474     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2475     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    2476     /// <param name="commandParameters">An array of SqlParamters to be cached</param>
    2477     public static void CacheParameterSet(string connectionString, string commandText, params SqlParameter[] commandParameters)
    2478     {
    2479       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2480       if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
    2481 
    2482       string hashKey = connectionString + ":" + commandText;
    2483 
    2484       paramCache[hashKey] = commandParameters;
    2485     }
    2486 
    2487     /// <summary>
    2488     /// Retrieve a parameter array from the cache
    2489     /// </summary>
    2490     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2491     /// <param name="commandText">The stored procedure name or T-SQL command</param>
    2492     /// <returns>An array of SqlParamters</returns>
    2493     public static SqlParameter[] GetCachedParameterSet(string connectionString, string commandText)
    2494     {
    2495       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2496       if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
    2497 
    2498       string hashKey = connectionString + ":" + commandText;
    2499 
    2500       SqlParameter[] cachedParameters = paramCache[hashKey] as SqlParameter[];
    2501       if (cachedParameters == null)
    2502       {
    2503         return null;
    2504       }
    2505       else
    2506       {
    2507         return CloneParameters(cachedParameters);
    2508       }
    2509     }
    2510 
    2511     #endregion caching functions
    2512 
    2513     #region Parameter Discovery Functions
    2514 
    2515     /// <summary>
    2516     /// Retrieves the set of SqlParameters appropriate for the stored procedure
    2517     /// </summary>
    2518     /// <remarks>
    2519     /// This method will query the database for this information, and then store it in a cache for future requests.
    2520     /// </remarks>
    2521     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2522     /// <param name="spName">The name of the stored procedure</param>
    2523     /// <returns>An array of SqlParameters</returns>
    2524     public static SqlParameter[] GetSpParameterSet(string connectionString, string spName)
    2525     {
    2526       return GetSpParameterSet(connectionString, spName, false);
    2527     }
    2528 
    2529     /// <summary>
    2530     /// Retrieves the set of SqlParameters appropriate for the stored procedure
    2531     /// </summary>
    2532     /// <remarks>
    2533     /// This method will query the database for this information, and then store it in a cache for future requests.
    2534     /// </remarks>
    2535     /// <param name="connectionString">A valid connection string for a SqlConnection</param>
    2536     /// <param name="spName">The name of the stored procedure</param>
    2537     /// <param name="includeReturnValueParameter">A bool value indicating whether the return value parameter should be included in the results</param>
    2538     /// <returns>An array of SqlParameters</returns>
    2539     public static SqlParameter[] GetSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
    2540     {
    2541       if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    2542       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2543 
    2544       using (SqlConnection connection = new SqlConnection(connectionString))
    2545       {
    2546         return GetSpParameterSetInternal(connection, spName, includeReturnValueParameter);
    2547       }
    2548     }
    2549 
    2550     /// <summary>
    2551     /// Retrieves the set of SqlParameters appropriate for the stored procedure
    2552     /// </summary>
    2553     /// <remarks>
    2554     /// This method will query the database for this information, and then store it in a cache for future requests.
    2555     /// </remarks>
    2556     /// <param name="connection">A valid SqlConnection object</param>
    2557     /// <param name="spName">The name of the stored procedure</param>
    2558     /// <returns>An array of SqlParameters</returns>
    2559     internal static SqlParameter[] GetSpParameterSet(SqlConnection connection, string spName)
    2560     {
    2561       return GetSpParameterSet(connection, spName, false);
    2562     }
    2563 
    2564     /// <summary>
    2565     /// Retrieves the set of SqlParameters appropriate for the stored procedure
    2566     /// </summary>
    2567     /// <remarks>
    2568     /// This method will query the database for this information, and then store it in a cache for future requests.
    2569     /// </remarks>
    2570     /// <param name="connection">A valid SqlConnection object</param>
    2571     /// <param name="spName">The name of the stored procedure</param>
    2572     /// <param name="includeReturnValueParameter">A bool value indicating whether the return value parameter should be included in the results</param>
    2573     /// <returns>An array of SqlParameters</returns>
    2574     internal static SqlParameter[] GetSpParameterSet(SqlConnection connection, string spName, bool includeReturnValueParameter)
    2575     {
    2576       if (connection == null) throw new ArgumentNullException("connection");
    2577       using (SqlConnection clonedConnection = (SqlConnection)((ICloneable)connection).Clone())
    2578       {
    2579         return GetSpParameterSetInternal(clonedConnection, spName, includeReturnValueParameter);
    2580       }
    2581     }
    2582 
    2583     /// <summary>
    2584     /// Retrieves the set of SqlParameters appropriate for the stored procedure
    2585     /// </summary>
    2586     /// <param name="connection">A valid SqlConnection object</param>
    2587     /// <param name="spName">The name of the stored procedure</param>
    2588     /// <param name="includeReturnValueParameter">A bool value indicating whether the return value parameter should be included in the results</param>
    2589     /// <returns>An array of SqlParameters</returns>
    2590     private static SqlParameter[] GetSpParameterSetInternal(SqlConnection connection, string spName, bool includeReturnValueParameter)
    2591     {
    2592       if (connection == null) throw new ArgumentNullException("connection");
    2593       if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    2594 
    2595       string hashKey = connection.ConnectionString + ":" + spName + (includeReturnValueParameter ? ":include ReturnValue Parameter" : "");
    2596 
    2597       SqlParameter[] cachedParameters;
    2598 
    2599       cachedParameters = paramCache[hashKey] as SqlParameter[];
    2600       if (cachedParameters == null)
    2601       {
    2602         SqlParameter[] spParameters = DiscoverSpParameterSet(connection, spName, includeReturnValueParameter);
    2603         paramCache[hashKey] = spParameters;
    2604         cachedParameters = spParameters;
    2605       }
    2606 
    2607       return CloneParameters(cachedParameters);
    2608     }
    2609 
    2610     #endregion Parameter Discovery Functions
    2611 
    2612   }
    2613 }
  • 相关阅读:
    gvim小操作
    gvim2笔记
    用JavaScript实现MD5,SHA1加密
    MYSQL性能优化(转)
    开源了,开放我的仿ext控件集
    个人js作品集,仿ext风格(改)
    sql查询 注意事项
    共轭矩阵
    wchar 转 int
    对象不能从 DBNull 转换为其他类型
  • 原文地址:https://www.cnblogs.com/seasons1987/p/2648495.html
Copyright © 2020-2023  润新知