using System; using System.Data; using System.Data.SqlClient; using System.Xml; namespace Neo.Afx.ComponentModel { /// /// Groups some SQL Server utility methods. /// public static class SqlUtilities { #region Fetch DataTable /// /// Executes the given Transact-SQL statement or stored procedure /// with the given (optional) parameters and returns a DataTable /// for the result set returned by the query. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The result of the command in a DataTable. public static DataTable FetchDataTable(string connectionString, string commandText, CommandType commandType, params SqlParameter[] parameters) { return FetchDataTable(CreateCommand(connectionString, commandText, commandType, parameters)); } /// /// Executes the given SqlCommand and returns a /// DataTable for the result set returned by the /// SqlCommand. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// when finished. /// /// /// The result of the command in a DataTable. public static DataTable FetchDataTable(this SqlCommand command) { return ExecuteReader(command, (CommandBehavior.SchemaOnly & CommandBehavior.KeyInfo), delegate(SqlDataReader reader) { var table = new DataTable(); table.Load(reader, LoadOption.OverwriteChanges); return table; }); } #endregion #region Create Command /// /// Creates a SqlCommand object with a new SqlConnection /// using the given connection string. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// The parameters of the Transact-SQL statement /// or stored procedure. If null or zero-length then no parameters /// are added. /// /// A new SqlCommand object. public static SqlCommand CreateCommand(string connectionString, string commandText, CommandType commandType, params SqlParameter[] parameters) { var cmd = new SqlCommand { Connection = new SqlConnection(connectionString), CommandText = commandText, CommandType = commandType }; if(parameters != null && parameters.Length > 0) { cmd.Parameters.AddRange(parameters); } return cmd; } #endregion #region Execute Command /// /// Executes the given command. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// when finished. /// /// /// The SqlCommand to be executed; /// must have a valid connection. /// /// The handler to be invoked. /// The result of invoking the /// The type of result returned. /// If handler is null. public static T ExecuteCommand(this SqlCommand command, CommandHandler handler) { if(handler != null) { T result; using(command) { using(command.Connection) { command.Connection.Open(); result = handler(command); } //"using" will close the connection even in case of exception. } return result; } throw new ArgumentNullException("handler"); } #endregion #region ExecuteNonQuery Method /// /// Executes the given Transact-SQL statement or stored procedure with /// the given (optional) parameters and returns the number of rows affected. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The number of rows affected. public static int ExecuteNonQuery(string connectionString, string commandText, CommandType commandType, params SqlParameter[] parameters) { return ExecuteNonQuery(CreateCommand(connectionString, commandText, commandType, parameters)); } /// /// Executes the given SqlCommand and returns the number /// of rows affected. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// when finished. /// /// /// The SqlCommand to be executed. /// /// The number of rows affected. public static int ExecuteNonQuery(this SqlCommand command) { return ExecuteCommand(command, cmd => cmd.ExecuteNonQuery()); } #endregion #region ExecuteScalar Method /// /// Executes the given Transact-SQL statement or stored procedure /// with the given (optional) parameters and returns the first column /// of the first row in the result set returned by the query. /// All other columns and rows are ignored. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The result of the Transact-SQL statement. /// The type of the result returned. public static T ExecuteScalar(string connectionString, string commandText, CommandType commandType, params SqlParameter[] parameters) { return ExecuteScalar(CreateCommand(connectionString, commandText, commandType, parameters)); } /// /// Executes the given SqlCommand and returns the first /// column of the first row in the result set returned by the query. /// All other columns and rows are ignored. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// when finished. /// /// /// The SqlCommand to be executed. /// /// The result of the Transact-SQL statement. /// The type of the result returned. public static T ExecuteScalar(this SqlCommand command) { return ExecuteCommand(command, delegate(SqlCommand cmd) { var scalar = cmd.ExecuteScalar(); if(scalar.IsNull()) { return default(T); } return (T)scalar; }); } #endregion #region ExecuteReader Method /// /// Invokes readerHandler with the SqlDataReader /// created for the given Transact-SQL statement or stored procedure /// with the given (optional) parameters. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// One of the CommandBehavior /// values. /// /// A method for consuming the generated reader. /// /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The result of the Transact-SQL statement. /// The type of the result returned. /// If handler is null. public static T ExecuteReader(string connectionString, string commandText, CommandType commandType, CommandBehavior commandBehavior, DataReaderHandler handler, params SqlParameter[] parameters) { return ExecuteReader(CreateCommand(connectionString, commandText, commandType, parameters), commandBehavior, handler); } /// /// Invokes readerHandler with the SqlDataReader /// created for the given SqlCommand. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// after the readerHandler returns. /// /// /// The SqlCommand to be executed. /// /// One of the CommandBehavior values. /// /// A method for consuming the generated reader. /// /// The results of executing readerHandler. /// The type of the result to be returned. /// If handler is null. public static T ExecuteReader(this SqlCommand command, CommandBehavior commandBehavior, DataReaderHandler handler) { if(handler != null) { return ExecuteCommand(command, delegate(SqlCommand cmd) { using(var reader = cmd.ExecuteReader(commandBehavior)) { return handler(reader); } }); } throw new ArgumentNullException("handler"); } /// /// Crerates a SqlDataReader for the given Transact-SQL statement /// or stored procedure with the given (optional) parameters. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// A value indicating how the commandText /// value is to be interpreted. /// One of the CommandBehavior /// values. /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The result of the Transact-SQL statement. /// public static SqlDataReader ExecuteReader(string connectionString, string commandText, CommandType commandType, CommandBehavior commandBehavior, params SqlParameter[] parameters) { return ExecuteReader(CreateCommand(connectionString, commandText, commandType, parameters), commandBehavior); } /// /// Creates a SqlDataReader for the given SqlCommand. /// /// The SqlCommand to be executed. /// One of the CommandBehavior values. /// /// The SqlDataReader. /// public static SqlDataReader ExecuteReader(this SqlCommand command, CommandBehavior commandBehavior) { if(command.Connection.State == ConnectionState.Closed) { command.Connection.Open(); } return command.ExecuteReader(commandBehavior); } #endregion #region ExecuteXmlReader Method /// /// Invokes readerHandler with the XmlReader /// created for the given Transact-SQL statement or stored procedure /// with the given (optional) parameters. /// /// The sql connection string. /// The Transact-SQL statement or /// stored procedure to execute. /// /// A value indicating how the commandText /// value is to be interpreted. /// /// A method for consuming the generated reader. /// /// The array of SqlParameters /// to be queried. /// If null or zero-length then no parameters are added. /// /// The result of the Transact-SQL statement. /// The type of the result returned. /// If handler is null. public static T ExecuteReader(string connectionString, string commandText, CommandType commandType, XmlReaderHandler handler, params SqlParameter[] parameters) { return ExecuteReader(CreateCommand(connectionString, commandText, commandType, parameters), handler); } /// /// Invokes readerHandler with the XmlReader /// created for the given SqlCommand. /// /// This method closes and disposes the /// SqlConnection and disposes the SqlCommand /// after the readerHandler returns. /// /// /// The SqlCommand to be executed. /// /// A method for consuming the generated reader. /// /// The results of executing readerHandler. /// The type of the result to be returned. /// If handler is null. public static T ExecuteReader(this SqlCommand command, XmlReaderHandler handler) { if(handler != null) { return ExecuteCommand(command, delegate(SqlCommand cmd) { using(var reader = cmd.ExecuteXmlReader()) { return handler(reader); } }); } throw new ArgumentNullException("handler"); } #endregion #region AddParameters Method /// /// Adds the given parameters to the given parameterized command. /// /// The parameterized command to be queried. /// The parameters of the Transact-SQL statement /// or stored procedure. May be null or must contain /// SqlParameter's or an even number of /// parameterName-parameterValue pairs. /// public static void AddParameters(this SqlCommand command, params object[] parameters) { if(parameters != null && parameters.Length > 0) { for(var i = 0; i < parameters.Length; i += 2) { if(parameters[i] is SqlParameter) { command.Parameters.Add((SqlParameter)parameters[i]); if(i < parameters.Length) { command.Parameters.Add((SqlParameter)parameters[i + 1]); } } else { command.Parameters.AddWithValue(parameters[i].ToString(), parameters[i + 1]); } } } } #endregion #region Convert To DbType /// /// Converts the given Type to a DbType. /// /// The type to be queried. /// A DbType. public static DbType ConvertToDbType(Type type) { // HACK : ToDbType if(type == typeof(Int16)) { return DbType.Int16; } if(type == typeof(Int32)) { return DbType.Int32; } if(type == typeof(Int64)) { return DbType.Int64; } if(type == typeof(Boolean)) { return DbType.Boolean; } if(type == typeof(Byte)) { return DbType.Byte; } if(type == typeof(DateTime)) { return DbType.DateTime; } if(type == typeof(Double)) { return DbType.Double; } if(type == typeof(Decimal)) { return DbType.Decimal; } if(type == typeof(Guid)) { return DbType.Guid; } if(type == typeof(SByte)) { return DbType.SByte; } if(type == typeof(Single)) { return DbType.Single; } if(type == typeof(String)) { return DbType.AnsiString; // varchar } if(type == typeof(XmlDocument)) { return DbType.Xml; } return DbType.Object; //object dummyInstance = Activator.CreateInstance(type); // We don't care what type of parameter we use; // the parameter is going to get thrown away. // Basically, we're creating a pseudointerface // to code hidden inside the parameter constructor. //SqlParameter dummyParameter = new SqlParameter("dummyname", dummyInstance); //return dummyParameter.DbType; } #endregion } #region Delegate Declarations /// /// A delegate for a method that processes an SqlDataReader /// and returns the results of that process. /// /// The SqlDataReader to be queried. /// The results of processing the SqlDataReader. /// The type of the result returned. public delegate T DataReaderHandler(SqlDataReader reader); /// /// A delegate for a method that handles an XmlReader /// and returns the results of that process. /// /// The XmlReader to be queried. /// The results of processing the XmlReader. /// The type of the result returned. public delegate T XmlReaderHandler(XmlReader reader); /// /// A delegate for a method that handles an IDbCommand /// and returns the results of that process. /// /// The IDbCommand to be executed. /// The results of processing the IDbCommand. /// The type of the result returned. public delegate T CommandHandler(SqlCommand command); #endregion }