/************************************************************************************ * * Umbraco Data Layer * MIT Licensed work * ©2008 Ruben Verborgh * ***********************************************************************************/ using System; using System.Data; using System.Diagnostics; using System.IO; using System.Xml; using umbraco.DataLayer.Utility; namespace umbraco.DataLayer { /// /// Abstract base class for SQL helpers that use parameters implementing IDataParameter. /// /// SQL parameter data type. public abstract class SqlHelper

: ISqlHelper where P : IDataParameter { #region Private Fields ///

The connection string that provides access to the SQL database. private readonly string m_ConnectionString; #endregion #region Protected Fields /// Utility that provides access to complex database actions. protected IUtilitySet m_Utility; #endregion #region Public Properties /// /// Gets the connection string that provides access to the SQL database. /// /// The connection string that provides access to the SQL database. public string ConnectionString { get { return m_ConnectionString; } } /// /// Gets the Umbraco utility associated with this SQL helper. /// /// The utilities. public IUtilitySet Utility { get { return m_Utility; } } #endregion #region Public Constructors /// /// Initializes a new instance of the class. /// /// The connection string. public SqlHelper(string connectionString) : this(connectionString, null) { } /// /// Initializes a new instance of the class. /// /// The connection string, cannot be null. /// The utility, a default utility will be used if null. public SqlHelper(string connectionString, IUtilitySet utility) { // Check arguments if (connectionString == null) throw new ArgumentNullException("connectionString"); if (utility == null) utility = new DefaultUtility>(this); // Initialize member fields m_ConnectionString = connectionString; m_Utility = utility; #if DEBUG && DebugDataLayer // Log creation Trace.TraceInformation(GetType().Name + " created."); #endif } /// /// Releases unmanaged resources and performs other cleanup operations before the /// is reclaimed by garbage collection. /// ~SqlHelper() { Dispose(); } #endregion #region Protected Methods /// /// Performs necessary conversion on the SQL command prior to its execution. /// /// The command text. /// The original command text. Inheriting classes can change this behavior. protected virtual string ConvertCommand(string commandText) { if (commandText == null) throw new ArgumentNullException("commandText"); return commandText; } /// /// Performs necessary conversion on the parameters prior to its execution. /// /// The parameters. Expected to be of type IParameterContainer. /// The parameters, converted to the raw types of their containers. protected virtual P[] ConvertParameters(IParameter[] parameters) { // Check arguments if (parameters == null) throw new ArgumentNullException("parameters"); // Add raw types of parameters to an array P[] newParams = new P[parameters.Length]; for (int index = 0; index < parameters.Length; index++) { // Get raw type out of container IParameterContainer

parameter = parameters[index] as IParameterContainer

; if (parameter == null) throw new ArgumentException( String.Format("Element {0} of parameters has the wrong type. Expected: IParameterContainer<{1}>. Received: {2}.", index, typeof(P).Name, (parameter==null ? "null" : parameter.GetType().Name)), "parameters"); newParams[index] = parameter.RawParameter; } return newParams; } ///

Converts the scalar value to the given type. /// Desired type of the value. /// A scalar returned by ExecuteScalar. /// The scalar, converted to type T. protected virtual T ConvertScalar(object scalar) { if (scalar == null || (scalar == DBNull.Value && !typeof(T).IsAssignableFrom(typeof(DBNull)))) return default(T); switch(typeof(T).FullName) { case "System.Int32": return (T)(object)int.Parse(scalar.ToString()); case "System.Int64": return (T)(object)long.Parse(scalar.ToString()); default: return (T)scalar; } } #endregion #region ISqlHelper Members /// /// Escapes a string for use in an SQL query. /// /// The value. /// The escaped value. /// You should use SQL parameters instead. public virtual string EscapeString(string value) { return string.IsNullOrEmpty(value) ? string.Empty : value.Replace("'", "''"); } /// /// Creates a new parameter for use with this specific implementation of ISqlHelper. /// /// Name of the parameter. /// Value of the parameter. /// A new parameter of the correct type. /// Abstract factory pattern public abstract IParameter CreateParameter(string parameterName, object value); /// /// Executes a command that returns a single value. /// /// The type of the value. /// The command text. /// The parameters. /// The return value of the command. /// If a data source error occurs. public T ExecuteScalar(string commandText, params IParameter[] parameters) { string commandConverted = ConvertCommand(commandText); P[] parametersConverted = ConvertParameters(parameters); try { return ConvertScalar(ExecuteScalar(commandConverted, parametersConverted)); } catch (Exception e) { throw new SqlHelperException("ExecuteScalar", commandText, parameters, e); } } /// /// Executes a command and returns the number of rows affected. /// /// The command text. /// The parameters. /// /// The number of rows affected by the command. /// /// If a data source error occurs. public int ExecuteNonQuery(string commandText, params IParameter[] parameters) { string commandConverted = ConvertCommand(commandText); P[] parametersConverted = ConvertParameters(parameters); try { return ExecuteNonQuery(commandConverted, parametersConverted); } catch (Exception e) { throw new SqlHelperException("ExecuteNonQuery", commandText, parameters, e); } } /// /// Executes a command and returns a records reader containing the results. /// /// The command text. /// The parameters. /// /// A data reader containing the results of the command. /// /// If a data source error occurs. public IRecordsReader ExecuteReader(string commandText, params IParameter[] parameters) { string commandConverted = ConvertCommand(commandText); P[] parametersConverted = ConvertParameters(parameters); try { return ExecuteReader(commandConverted, parametersConverted); } catch (Exception e) { throw new SqlHelperException("ExecuteReader", commandText, parameters, e); } } /// /// Executes a command that returns an XML value. /// /// The command text. /// The parameters. /// /// An XML reader containing the return value. /// /// If a data source error occurs. public XmlReader ExecuteXmlReader(string commandText, params IParameter[] parameters) { string commandConverted = ConvertCommand(commandText); P[] parametersConverted = ConvertParameters(parameters); try { return ExecuteXmlReader(commandConverted, parametersConverted); } catch (Exception e) { throw new SqlHelperException("ExecuteXmlReader", commandText, parameters, e); } } #endregion #region Abstract Query Methods /// /// Executes a command that returns a single value. /// /// The command text. /// The parameters. /// The return value of the command. protected abstract object ExecuteScalar(string commandText, P[] parameters); /// /// Executes a command and returns the number of rows affected. /// /// The command text. /// The parameters. /// /// The number of rows affected by the command. /// protected abstract int ExecuteNonQuery(string commandText, params P[] parameters); /// /// Executes a command and returns a records reader containing the results. /// /// The command text. /// The parameters. /// /// A data reader containing the results of the command. /// protected abstract IRecordsReader ExecuteReader(string commandText, params P[] parameters); /// /// Executes a command that returns an XML value. /// /// The command text. /// The parameters. /// /// An XML reader containing the return value. /// protected virtual XmlReader ExecuteXmlReader(string commandText, params P[] parameters) { string xmlString = (string)ExecuteScalar(commandText, parameters); if (xmlString == null) throw new ArgumentException("The query didn't return a value."); return XmlReader.Create(new StringReader(xmlString)); } #endregion #region IDisposable Members /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public virtual void Dispose() { } #endregion } }