using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.SqlTypes; using System.Diagnostics; using System.Text; namespace BLToolkit.Data { using Common; using DataProvider; using Mapping; using Properties; using Reflection; using Sql; /// /// The DbManager is a primary class of the namespace /// that can be used to execute commands of different database providers. /// /// /// When the DbManager goes out of scope, it does not close the internal connection object. /// Therefore, you must explicitly close the connection by calling or /// . Also, you can use the C# using statement. /// /// [DesignerCategory("Code")] public partial class DbManager: Component { #region Constructors public DbManager(DataProviderBase dataProvider, string connectionString) { if (dataProvider == null) throw new ArgumentNullException("dataProvider"); if (connectionString == null) throw new ArgumentNullException("connectionString"); _dataProvider = dataProvider; _connection = dataProvider.CreateConnectionObject(); _connection.ConnectionString = connectionString; _dataProvider.InitDbManager(this); } public DbManager(DataProviderBase dataProvider, IDbConnection connection) { if (dataProvider == null) throw new ArgumentNullException("dataProvider"); if (connection == null) throw new ArgumentNullException("connection"); _dataProvider = dataProvider; _connection = connection; _dataProvider.InitDbManager(this); } public DbManager(DataProviderBase dataProvider, IDbTransaction transaction) { if (dataProvider == null) throw new ArgumentNullException("dataProvider"); if (transaction == null) throw new ArgumentNullException("transaction"); _dataProvider = dataProvider; _connection = transaction.Connection; _transaction = transaction; _closeTransaction = false; _dataProvider.InitDbManager(this); } DbManager(int n) { } public DbManager Clone() { DbManager clone = new DbManager(0); clone._configurationString = _configurationString; clone._dataProvider = _dataProvider; clone._mappingSchema = _mappingSchema; if (_connection != null) clone._connection = CloneConnection(); return clone; } #endregion #region Public Properties private MappingSchema _mappingSchema = Map.DefaultSchema; /// /// Gets the /// used by this instance of the . /// /// /// A mapping schema. /// public MappingSchema MappingSchema { [DebuggerStepThrough] get { return _mappingSchema; } set { _mappingSchema = value ?? Map.DefaultSchema; } } private DataProviderBase _dataProvider; /// /// Gets the /// used by this instance of the . /// /// /// A data provider. /// /// public DataProviderBase DataProvider { [DebuggerStepThrough] get { return _dataProvider; } protected set { _dataProvider = value; } } private static TraceSwitch _traceSwitch; public static TraceSwitch TraceSwitch { get { return _traceSwitch ?? (_traceSwitch = new TraceSwitch("DbManager", "DbManager trace switch", "Warning")); } set { _traceSwitch = value; } } private bool _canRaiseEvents = true; public new bool CanRaiseEvents { get { return _canRaiseEvents && base.CanRaiseEvents; } set { _canRaiseEvents = value; } } #endregion #region Connection private bool _closeConnection; private IDbConnection _connection; /// /// Gets or sets the used by this instance of the . /// /// /// The connection to the data source. /// /// /// Then you set a connection object, it has to match the data source type. /// /// /// A connection does not match the data source type. /// /// public IDbConnection Connection { [DebuggerStepThrough] get { if (_connection.State == ConnectionState.Closed) OpenConnection(); return _connection; } set { if (value == null) throw new ArgumentNullException("value"); if (value.GetType() != _dataProvider.ConnectionType) InitDataProvider(value); _connection = value; _closeConnection = false; } } [Obsolete] protected virtual string GetConnectionString(IDbConnection connection) { return connection.ConnectionString; } private void OpenConnection() { ExecuteOperation(OperationType.OpenConnection, _connection.Open); _closeConnection = true; } /// /// Closes the connection to the database. /// /// /// The Close method rolls back any pending transactions /// and then closes the connection. /// /// /// public void Close() { if (OnClosing != null) OnClosing(this, EventArgs.Empty); if (_selectCommand != null) { _selectCommand.Dispose(); _selectCommand = null; } if (_insertCommand != null) { _insertCommand.Dispose(); _insertCommand = null; } if (_updateCommand != null) { _updateCommand.Dispose(); _updateCommand = null; } if (_deleteCommand != null) { _deleteCommand.Dispose(); _deleteCommand = null; } if (_transaction != null && _closeTransaction) { ExecuteOperation(OperationType.DisposeTransaction, _transaction.Dispose); _transaction = null; } if (_connection != null && _closeConnection) { ExecuteOperation(OperationType.CloseConnection, _connection.Dispose); _connection = null; } if (OnClosed != null) OnClosed(this, EventArgs.Empty); } #endregion #region Transactions private bool _closeTransaction = true; private IDbTransaction _transaction; /// /// Gets the used by this instance of the . /// /// /// The . The default value is a null reference. /// /// /// You have to call the method to begin a transaction. /// /// /// public IDbTransaction Transaction { [DebuggerStepThrough] get { return _transaction; } } /// /// Begins a database transaction. /// /// /// Once the transaction has completed, you must explicitly commit or roll back the transaction /// by using the > or /// methods. /// /// /// This instance of the . /// public virtual DbManager BeginTransaction() { return BeginTransaction(IsolationLevel.ReadCommitted); } /// /// Begins a database transaction with the specified value. /// /// /// Once the transaction has completed, you must explicitly commit or roll back the transaction /// by using the or /// methods. /// /// /// One of the values. /// This instance of the . public virtual DbManager BeginTransaction(IsolationLevel il) { // If transaction is open, we dispose it, it will rollback all changes. // if (_transaction != null) { ExecuteOperation(OperationType.DisposeTransaction, _transaction.Dispose); } // Create new transaction object. // _transaction = ExecuteOperation(OperationType.BeginTransaction, delegate { return Connection.BeginTransaction(il); }); _closeTransaction = true; // If the active command exists. // if (_selectCommand != null) _selectCommand.Transaction = _transaction; if (_insertCommand != null) _insertCommand.Transaction = _transaction; if (_updateCommand != null) _updateCommand.Transaction = _transaction; if (_deleteCommand != null) _deleteCommand.Transaction = _transaction; return this; } /// /// Commits the database transaction. /// /// This instance of the . public virtual DbManager CommitTransaction() { if (_transaction != null) { ExecuteOperation(OperationType.CommitTransaction, _transaction.Commit); if (_closeTransaction) _transaction = null; } return this; } /// /// Rolls back a transaction from a pending state. /// /// This instance of the . public virtual DbManager RollbackTransaction() { if (_transaction != null) { ExecuteOperation(OperationType.RollbackTransaction, _transaction.Rollback); if (_closeTransaction) _transaction = null; } return this; } #endregion #region Commands private IDbCommand _selectCommand; /// /// Gets the used by this instance of the . /// /// /// A used during executing query. /// /// /// The Command can be used to access command parameters. /// /// public IDbCommand Command { [DebuggerStepThrough] get { return SelectCommand; } } /// /// Gets the select used by this instance of the . /// /// /// A used during executing query. /// /// /// The SelectCommand can be used to access select command parameters. /// /// public IDbCommand SelectCommand { [DebuggerStepThrough] get { return _selectCommand = OnInitCommand(_selectCommand); } } private IDbCommand _insertCommand; /// /// Gets the insert used by this instance of the . /// /// /// A used during executing query. /// /// /// The InsertCommand can be used to access insert command parameters. /// /// public IDbCommand InsertCommand { [DebuggerStepThrough] get { return _insertCommand = OnInitCommand(_insertCommand); } } private IDbCommand _updateCommand; /// /// Gets the update used by this instance of the . /// /// /// A used during executing query. /// /// /// The UpdateCommand can be used to access update command parameters. /// /// public IDbCommand UpdateCommand { [DebuggerStepThrough] get { return _updateCommand = OnInitCommand(_updateCommand); } } private IDbCommand _deleteCommand; /// /// Gets the delete used by this instance of the . /// /// /// A used during executing query. /// /// /// The DeleteCommand can be used to access delete command parameters. /// /// public IDbCommand DeleteCommand { [DebuggerStepThrough] get { return _deleteCommand = OnInitCommand(_deleteCommand); } } /// /// Initializes a command and raises the event. /// protected virtual IDbCommand OnInitCommand(IDbCommand command) { if (command == null) { // Create a command object. // command = _dataProvider.CreateCommandObject(Connection); // If an active transaction exists. // if (Transaction != null) { command.Transaction = Transaction; } } if (CanRaiseEvents) { InitCommandEventHandler handler = (InitCommandEventHandler)Events[EventInitCommand]; if (handler != null) handler(this, new InitCommandEventArgs(command)); } return command; } /// /// Helper function. Creates the command object and sets command type and command text. /// /// Command action. /// The /// (stored procedure, text, etc.) /// The SQL statement. /// The command object. private IDbCommand GetCommand(CommandAction commandAction, CommandType commandType, string sql) { IDbCommand command = GetCommand(commandAction); command.Parameters.Clear(); command.CommandType = commandType; command.CommandText = sql; return command; } #endregion #region Events public event EventHandler OnClosing; public event EventHandler OnClosed; private static readonly object EventBeforeOperation = new object(); /// /// Occurs when a server-side operation is about to start. /// public event OperationTypeEventHandler BeforeOperation { add { Events.AddHandler (EventBeforeOperation, value); } remove { Events.RemoveHandler(EventBeforeOperation, value); } } private static readonly object EventAfterOperation = new object(); /// /// Occurs when a server-side operation is complete. /// public event OperationTypeEventHandler AfterOperation { add { Events.AddHandler (EventAfterOperation, value); } remove { Events.RemoveHandler(EventAfterOperation, value); } } private static readonly object EventOperationException = new object(); /// /// Occurs when a server-side operation is failed to execute. /// public event OperationExceptionEventHandler OperationException { add { Events.AddHandler (EventOperationException, value); } remove { Events.RemoveHandler(EventOperationException, value); } } private static readonly object EventInitCommand = new object(); /// /// Occurs when the is initializing. /// public event InitCommandEventHandler InitCommand { add { Events.AddHandler (EventInitCommand, value); } remove { Events.RemoveHandler(EventInitCommand, value); } } /// /// Raises the event. /// /// The . protected virtual void OnBeforeOperation(OperationType op) { if (CanRaiseEvents) { OperationTypeEventHandler handler = (OperationTypeEventHandler)Events[EventBeforeOperation]; if (handler != null) handler(this, new OperationTypeEventArgs(op)); } } /// /// Raises the event. /// /// The . protected virtual void OnAfterOperation(OperationType op) { if (CanRaiseEvents) { OperationTypeEventHandler handler = (OperationTypeEventHandler)Events[EventAfterOperation]; if (handler != null) handler(this, new OperationTypeEventArgs(op)); } } /// /// Raises the event. /// /// The . /// The occurred. protected virtual void OnOperationException(OperationType op, DataException ex) { if (CanRaiseEvents) { OperationExceptionEventHandler handler = (OperationExceptionEventHandler)Events[EventOperationException]; if (handler != null) handler(this, new OperationExceptionEventArgs(op, ex)); } throw ex; } #endregion #region Protected Methods private IDataReader ExecuteReaderInternal() { return ExecuteReader(CommandBehavior.Default); } private IDataReader ExecuteReaderInternal(CommandBehavior commandBehavior) { return ExecuteOperation(OperationType.ExecuteReader, delegate { return _dataProvider.GetDataReader(_mappingSchema, SelectCommand.ExecuteReader(commandBehavior)); }); } private int ExecuteNonQueryInternal() { return ExecuteOperation(OperationType.ExecuteNonQuery, SelectCommand.ExecuteNonQuery); } #endregion #region Parameters private IDbDataParameter[] CreateSpParameters(string spName, object[] parameterValues, bool openNewConnectionToDiscoverParameters) { // Pull the parameters for this stored procedure from // the parameter cache (or discover them & populate the cache) // IDbDataParameter[] commandParameters = GetSpParameters(spName, true, openNewConnectionToDiscoverParameters); // DbParameters are bound by name, plain parameters by order // bool dbParameters = false; if (parameterValues == null || parameterValues.Length == 0 || parameterValues[0] is IDbDataParameter || parameterValues[0] is IDbDataParameter[]) { // The PrepareParameters method may add some additional parameters. // parameterValues = PrepareParameters(parameterValues); if (parameterValues == null || parameterValues.Length == 0) return commandParameters; dbParameters = true; } if (commandParameters == null/* || commandParameters.Length == 0*/) { commandParameters = new IDbDataParameter[parameterValues.Length]; if (dbParameters) { parameterValues.CopyTo(commandParameters, 0); } else { for (int i = 0; i < parameterValues.Length; i++) commandParameters[i] = Parameter("?", parameterValues[i]); } return commandParameters; } if (dbParameters) { // If we receive an array of IDbDataParameter, // we need to copy parameters to the IDbDataParameter[]. // for (int i = 0; i < commandParameters.Length; i++) { IDbDataParameter param = commandParameters[i]; string name = param.ParameterName; bool found = false; foreach (IDbDataParameter p in parameterValues) { if (string.Compare(name, p.ParameterName, true) == 0) { if (param.Direction != p.Direction) { Debug.WriteLineIf(TraceSwitch.TraceWarning, string.Format( "Stored Procedure '{0}'. Parameter '{1}' has different direction '{2}'. Should be '{3}'.", spName, name, param.Direction, p.Direction), TraceSwitch.DisplayName); param.Direction = p.Direction; } if (param.Direction != ParameterDirection.Output) param.Value = p.Value; p.ParameterName = name; found = true; break; } } if (found == false && ( param.Direction == ParameterDirection.Input || param.Direction == ParameterDirection.InputOutput)) { Debug.WriteLineIf(TraceSwitch.TraceWarning, string.Format( "Stored Procedure '{0}'. Parameter '{1}' not assigned.", spName, name), TraceSwitch.DisplayName); param.SourceColumn = _dataProvider.Convert(name, ConvertType.ParameterToName).ToString(); } } } else { // Assign the provided values to the parameters based on parameter order. // AssignParameterValues(commandParameters, parameterValues); } return commandParameters; } /// /// Creates an one-dimension array of /// from any combination on IDbDataParameter, IDbDataParameter[] or null references. /// Null references are stripped, arrays and single parameters are combined /// into a new array. /// /// When two or more parameters has the same name, /// the first parameter is used, all the rest are ignored. ///Array of IDbDataParameter, IDbDataParameter[] or null references. ///An normalized array of without null references. ///The parameter /// contains anything except IDbDataParameter, IDbDataParameter[] or null reference. public virtual IDbDataParameter[] PrepareParameters(object[] parameters) { if (parameters == null || parameters.Length == 0) return null; // Little optimization. // Check if we have only one single ref parameter. // object refParam = null; for (int i = 0; i < parameters.Length; i++) { if (parameters[i] != null) { if (refParam != null) { refParam = null; break; } refParam = parameters[i]; } } if (refParam is IDbDataParameter[]) { return (IDbDataParameter[])refParam; } if (refParam is IDbDataParameter) { IDbDataParameter[] oneParameterArray = new IDbDataParameter[1]; oneParameterArray[0] = (IDbDataParameter)refParam; return oneParameterArray; } List list = new List(parameters.Length); Dictionary hash = new Dictionary(parameters.Length); foreach (object o in parameters) { if (o is IDbDataParameter) { IDbDataParameter p = (IDbDataParameter)o; if (!hash.ContainsKey(p.ParameterName)) { list.Add(p); hash.Add(p.ParameterName, p); } } else if (o is IDbDataParameter[]) { foreach (IDbDataParameter p in (IDbDataParameter[])o) { if (!hash.ContainsKey(p.ParameterName)) { list.Add(p); hash.Add(p.ParameterName, p); } } } else if (o != null && o != DBNull.Value) { throw new ArgumentException( Resources.DbManager_NotDbDataParameter, "parameters"); } } return list.ToArray(); } /// /// This method is used to attach array of to a . /// /// The command to which the parameters will be added /// An array of IDbDataParameters tho be added to command private void AttachParameters(IDbCommand command, IDbDataParameter[] commandParameters) { command.Parameters.Clear(); foreach (IDbDataParameter p in commandParameters) { _dataProvider.AttachParameter(command, p); } } private static readonly Dictionary _paramCache = new Dictionary(); private static readonly object _paramCacheLock = new object(); /// /// Resolve at run time the appropriate set of parameters for a stored procedure. /// /// The name of the stored procedure. /// Whether or not to include their return value parameter. /// protected virtual IDbDataParameter[] DiscoverSpParameters(string spName, bool includeReturnValueParameter, bool openNewConnection) { IDbConnection con = openNewConnection ? CloneConnection() : _connection; try { if (con.State == ConnectionState.Closed) { ExecuteOperation(OperationType.OpenConnection, con.Open); if (!openNewConnection) _closeConnection = true; } using (IDbCommand cmd = con.CreateCommand()) { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = spName; bool res = ExecuteOperation(OperationType.DeriveParameters, delegate { return _dataProvider.DeriveParameters(cmd); }); ExecuteOperation(OperationType.CloseConnection, con.Close); if (res == false) return null; if (includeReturnValueParameter == false) { // All known data providers always treat // the return value as first parameter. // cmd.Parameters.RemoveAt(0); } IDbDataParameter[] discoveredParameters = new IDbDataParameter[cmd.Parameters.Count]; cmd.Parameters.CopyTo(discoveredParameters, 0); return discoveredParameters; } } finally { if (con != null && openNewConnection) con.Dispose(); } } /// /// Copies cached parameter array. /// /// The original parameter array. /// The result array. private IDbDataParameter[] CloneParameters(IDbDataParameter[] originalParameters) { if (originalParameters == null) return null; IDbDataParameter[] clonedParameters = new IDbDataParameter[originalParameters.Length]; for (int i = 0, j = originalParameters.Length; i < j; i++) { clonedParameters[i] = _dataProvider.CloneParameter(originalParameters[i]); } return clonedParameters; } /// /// Retrieves the set of parameters appropriate for the stored procedure. /// /// /// This method will query the database for this information, /// and then store it in a cache for future requests. /// /// The name of the stored procedure. /// A boolean value indicating /// whether the return value parameter should be included in the results. /// An array of the . public IDbDataParameter[] GetSpParameters(string spName, bool includeReturnValueParameter, bool openNewConnectionToDiscoverParameters) { string key = string.Format("{0}:{1}:{2}", GetConnectionHash(), spName, includeReturnValueParameter); IDbDataParameter[] cachedParameters; // It is thread safe enought to check for a key and get its value without a lock. // if (!_paramCache.TryGetValue(key, out cachedParameters)) { lock (_paramCacheLock) { // There is a possible race condition since the operation may took a time. // if (!_paramCache.TryGetValue(key, out cachedParameters)) { cachedParameters = DiscoverSpParameters(spName, includeReturnValueParameter, openNewConnectionToDiscoverParameters); _paramCache.Add(key, cachedParameters); } } } return CloneParameters(cachedParameters); } /// /// This method assigns an array of values to an array of parameters. /// /// array of IDbDataParameters to be assigned values /// array of objects holding the values to be assigned private void AssignParameterValues(IDbDataParameter[] commandParameters, object[] parameterValues) { if (commandParameters == null || parameterValues == null) { // Do nothing if we get no data. // return; } int nValues = 0; // Iterate through the parameters, assigning the values from // the corresponding position in the value array. // for (int i = 0; i < commandParameters.Length; i++) { IDbDataParameter parameter = commandParameters[i]; if (_dataProvider.IsValueParameter(parameter)) { if (nValues >= parameterValues.Length) throw new ArgumentException(Resources.DbManager_MismatchParameterCount); object value = parameterValues[nValues++]; parameter.Value = value ?? DBNull.Value; //_dataProvider.SetParameterType(parameter, value); } } // We must have the same number of values as we pave parameters to put them in. // if (nValues != parameterValues.Length) throw new ArgumentException(Resources.DbManager_MismatchParameterCount); } /// /// Assigns a business object to command parameters. /// /// /// Assigns the to command parameters. /// /// /// /// The method is used in addition to the method. /// /// The to assign. /// This instance of the . public DbManager AssignParameterValues(DataRow dataRow) { if (dataRow == null) throw new ArgumentNullException("dataRow"); foreach (DataColumn c in dataRow.Table.Columns) { if (c.AutoIncrement == false && c.ReadOnly == false) { object o = dataRow[c.ColumnName]; string name = _dataProvider.Convert(c.ColumnName, ConvertType.NameToParameter).ToString(); Parameter(name).Value = c.AllowDBNull && _mappingSchema.IsNull(o)? DBNull.Value: o; } } if (_prepared) InitParameters(CommandAction.Select); return this; } /// /// Assigns a business object to command parameters. /// /// /// The method is used in addition to the method. /// /// /// An object to assign. /// This instance of the . public DbManager AssignParameterValues(object obj) { if (obj == null) throw new ArgumentNullException("obj"); ObjectMapper om = _mappingSchema.GetObjectMapper(obj.GetType()); foreach (MemberMapper mm in om) { string name = _dataProvider.Convert(mm.Name, ConvertType.NameToParameter).ToString(); if (Command.Parameters.Contains(name)) { object value = mm.GetValue(obj); Parameter(name).Value = value == null || mm.MapMemberInfo.Nullable && _mappingSchema.IsNull(value)? DBNull.Value: value; } } if (_prepared) InitParameters(CommandAction.Select); return this; } private static Array SortArray(Array array, IComparer comparer) { if (array == null) return null; Array arrayClone = (Array)array.Clone(); Array.Sort(arrayClone, comparer); return arrayClone; } /// /// Creates an array of parameters from the object. /// /// /// The method can take an additional parameter list, /// which can be created by using the same method. /// /// /// The to create parameters. /// An array of parameters to be added to the result array. /// An array of parameters. public IDbDataParameter[] CreateParameters( DataRow dataRow, params IDbDataParameter[] commandParameters) { return CreateParameters(dataRow, null, null, null, commandParameters); } /// /// Creates an array of parameters from the object. /// /// /// The method can take an additional parameter list, /// which can be created by using the same method. /// /// /// The to create parameters. /// Output parameters names. /// InputOutput parameters names. /// Parameters names to skip. /// An array of parameters to be added to the result array. /// An array of parameters. public IDbDataParameter[] CreateParameters( DataRow dataRow, string[] outputParameters, string[] inputOutputParameters, string[] ignoreParameters, params IDbDataParameter[] commandParameters) { if (dataRow == null) throw new ArgumentNullException("dataRow"); ArrayList paramList = new ArrayList(); IComparer comparer = CaseInsensitiveComparer.Default; outputParameters = (string[])SortArray(outputParameters, comparer); inputOutputParameters = (string[])SortArray(inputOutputParameters, comparer); ignoreParameters = (string[])SortArray(ignoreParameters, comparer); foreach (DataColumn c in dataRow.Table.Columns) { if (ignoreParameters != null && Array.BinarySearch(ignoreParameters, c.ColumnName, comparer) >= 0) continue; if (c.AutoIncrement || c.ReadOnly) continue; string name = _dataProvider.Convert(c.ColumnName, ConvertType.NameToParameter).ToString(); IDbDataParameter parameter = c.AllowDBNull? NullParameter(name, dataRow[c.ColumnName]): Parameter (name, dataRow[c.ColumnName]); if (outputParameters != null && Array.BinarySearch(outputParameters, c.ColumnName, comparer) >= 0) parameter.Direction = ParameterDirection.Output; else if (inputOutputParameters != null && Array.BinarySearch(inputOutputParameters, c.ColumnName, comparer) >= 0) parameter.Direction = ParameterDirection.InputOutput; paramList.Add(parameter); } if (commandParameters != null) paramList.AddRange(commandParameters); return (IDbDataParameter[])paramList.ToArray(typeof(IDbDataParameter)); } /// /// Creates an array of parameters from a business object. /// /// /// The method can take an additional parameter list, /// which can be created by using the same method. /// /// /// An object. /// An array of parameters to be added to the result array. /// An array of parameters. public IDbDataParameter[] CreateParameters( object obj, params IDbDataParameter[] commandParameters) { return CreateParameters(obj, null, null, null, commandParameters); } /// /// Creates an array of parameters from a business object. /// /// /// The method can take an additional parameter list, /// which can be created by using the same method. /// /// /// An object. /// Output parameters names. /// InputOutput parameters names. /// Parameters names to skip. /// An array of parameters to be added to the result array. /// An array of parameters. public IDbDataParameter[] CreateParameters( object obj, string[] outputParameters, string[] inputOutputParameters, string[] ignoreParameters, params IDbDataParameter[] commandParameters) { if (obj == null) throw new ArgumentNullException("obj"); bool isType = obj is Type; Type type = isType? (Type)obj: obj.GetType(); ObjectMapper om = _mappingSchema.GetObjectMapper(type); ArrayList paramList = new ArrayList(); IComparer comparer = CaseInsensitiveComparer.Default; outputParameters = (string[])SortArray(outputParameters, comparer); inputOutputParameters = (string[])SortArray(inputOutputParameters, comparer); ignoreParameters = (string[])SortArray(ignoreParameters, comparer); foreach (MemberMapper mm in om) { if (ignoreParameters != null && Array.BinarySearch(ignoreParameters, mm.Name, comparer) >= 0) continue; object value = isType? null: mm.GetValue(obj); string name = _dataProvider.Convert(mm.Name, ConvertType.NameToParameter).ToString(); IDbDataParameter parameter = mm.MapMemberInfo.Nullable || value == null? NullParameter(name, value, mm.MapMemberInfo.NullValue): (mm.DbType != DbType.Object)? Parameter (name, value, mm.DbType ): Parameter (name, value); if (outputParameters != null && Array.BinarySearch(outputParameters, mm.Name, comparer) >= 0) parameter.Direction = ParameterDirection.Output; else if (inputOutputParameters != null && Array.BinarySearch(inputOutputParameters, mm.Name, comparer) >= 0) parameter.Direction = ParameterDirection.InputOutput; paramList.Add(parameter); } if (commandParameters != null) paramList.AddRange(commandParameters); return (IDbDataParameter[])paramList.ToArray(typeof(IDbDataParameter)); } /// /// Maps all parameters returned from the server to all given objects. /// /// Name of a to map return value. /// An to map from command parameters. public void MapOutputParameters( string returnValueMember, object obj) { IMapDataDestination dest = _mappingSchema.GetDataDestination(obj); foreach (IDbDataParameter parameter in Command.Parameters) { int ordinal = -1; switch (parameter.Direction) { case ParameterDirection.InputOutput: case ParameterDirection.Output: ordinal = dest.GetOrdinal( _dataProvider.Convert(parameter.ParameterName, ConvertType.ParameterToName).ToString()); break; case ParameterDirection.ReturnValue: if (returnValueMember != null) { if (!returnValueMember.StartsWith("@") && dest is ObjectMapper) { ObjectMapper om = (ObjectMapper)dest; MemberAccessor ma = om.TypeAccessor[returnValueMember]; if (ma != null) { ma.SetValue(obj, _mappingSchema.ConvertChangeType(parameter.Value, ma.Type)); continue; } } else { returnValueMember = returnValueMember.Substring(1); } ordinal = dest.GetOrdinal(returnValueMember); } break; } if (ordinal >= 0) dest.SetValue(obj, ordinal, _mappingSchema.ConvertChangeType(parameter.Value, dest.GetFieldType(ordinal))); } } /// /// Maps all parameters returned from the server to an object. /// /// An to map from command parameters. /// from command parameters. public void MapOutputParameters(object obj) { MapOutputParameters(null, obj); } /// /// Maps all parameters returned from the server to all given objects. /// /// Name of the member used to map the /// return value. Can be null. /// An array of to map /// from command parameters. public void MapOutputParameters(string returnValueMember, params object[] objects) { if (objects == null) return; foreach (object obj in objects) MapOutputParameters(returnValueMember, obj); } /// /// Maps all parameters returned from the server to an object. /// /// An array of to map /// from command parameters. public void MapOutputParameters(params object[] objects) { MapOutputParameters(null, objects); } /// /// Adds a parameter to the or returns existing one. /// /// /// Returns an existing parameter. /// /// /// The method can be used to retrieve return and output parameters. /// /// /// The name of the parameter. /// The object. public IDbDataParameter Parameter(string parameterName) { return _dataProvider.GetParameter(Command, parameterName); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter Parameter(string parameterName, object value) { return Parameter(ParameterDirection.Input, parameterName, value); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// /// The name of the parameter. /// One of the values. /// The object. public IDbDataParameter Parameter(string parameterName, DbType dbType) { return Parameter(ParameterDirection.Input, parameterName, dbType); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// /// The name of the parameter. /// One of the values. /// Size of the parameter. /// The object. public IDbDataParameter Parameter(string parameterName, DbType dbType, int size) { return Parameter(ParameterDirection.Input, parameterName, dbType, size); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// If the parameter is null, it's converted to .. /// /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter NullParameter(string parameterName, object value) { if (_mappingSchema.IsNull(value)) @value = DBNull.Value; return Parameter(ParameterDirection.Input, parameterName, value); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The null equivalent to compare with the value. /// The object. public IDbDataParameter NullParameter(string parameterName, object value, object nullValue) { if (value == null || value.Equals(nullValue)) @value = DBNull.Value; return Parameter(ParameterDirection.Input, parameterName, value); } /// /// Adds an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type. /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter InputParameter(string parameterName, object value) { return Parameter(ParameterDirection.Input, parameterName, value); } /// /// Adds an output parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Output type. /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter OutputParameter(string parameterName, object value) { return Parameter(ParameterDirection.Output, parameterName, value); } /// /// Adds an output parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Output type. /// /// The name of the parameter. /// One of the values. /// that is the value of the parameter. /// The object. public IDbDataParameter OutputParameter(string parameterName, DbType dbType) { return Parameter(ParameterDirection.Output, parameterName, dbType); } /// /// Adds an output parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Output type. /// /// The name of the parameter. /// One of the values. /// Size of the parameter. /// that is the value of the parameter. /// The object. public IDbDataParameter OutputParameter(string parameterName, DbType dbType, int size) { return Parameter(ParameterDirection.Output, parameterName, dbType, size); } /// /// Adds an input-output parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.InputOutput type. /// /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter InputOutputParameter(string parameterName, object value) { return Parameter(ParameterDirection.InputOutput,parameterName, value); } /// /// Adds a return value parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.ReturnValue type. /// /// The name of the parameter. /// The object. public IDbDataParameter ReturnValue(string parameterName) { return Parameter(ParameterDirection.ReturnValue, parameterName, null); } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// The /// that is the value of the parameter. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, object value) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; //_dataProvider.SetParameterType(parameter, value); parameter.Value = value ?? DBNull.Value; return parameter; } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// The /// that is the value of the parameter. /// One of the values. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, object value, DbType dbType) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; parameter.DbType = dbType; parameter.Value = value; return parameter; } /// /// Adds an input parameter to the . /// /// The name of the parameter. /// The /// that is the value of the parameter. /// One of the values. /// The object. public IDbDataParameter Parameter( string parameterName, object value, DbType dbType) { return Parameter(ParameterDirection.Input, parameterName, value, dbType); } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// The /// that is the value of the parameter. /// One of the values. /// Size of the parameter. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, object value, DbType dbType, int size) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; parameter.DbType = dbType; parameter.Size = size; parameter.Value = value; return parameter; } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// The /// that is the value of the parameter. /// User defined type name for a table-valued parameter. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, object value, string typeName) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; _dataProvider.SetUserDefinedType(parameter, typeName); parameter.Value = value; return parameter; } /// /// Adds an input parameter to the . /// /// The name of the parameter. /// The /// that is the value of the parameter. /// One of the values. /// Size of the parameter. /// The object. public IDbDataParameter Parameter( string parameterName, object value, DbType dbType, int size) { return Parameter(ParameterDirection.Input, parameterName, value, dbType, size); } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// One of the values. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, DbType dbType) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; parameter.DbType = dbType; return parameter; } /// /// Adds a parameter to the . /// /// /// The method creates a parameter with the specified /// type. /// /// One of the values. /// The name of the parameter. /// One of the values. /// Size of the parameter. /// The object. public IDbDataParameter Parameter( ParameterDirection parameterDirection, string parameterName, DbType dbType, int size) { IDbDataParameter parameter = _dataProvider.CreateParameterObject(Command); parameter.ParameterName = parameterName; parameter.Direction = parameterDirection; parameter.DbType = dbType; parameter.Size = size; return parameter; } /// /// Creates an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type /// and DataRowVersion.Current type. /// /// The name of the parameter. /// One of the values. /// Size of the parameter. /// Source column for a parameter in the . /// The object. public IDbDataParameter Parameter( string parameterName, DbType dbType, int size, string sourceColumn) { IDbDataParameter param = Parameter(ParameterDirection.Input, parameterName, dbType, size); param.SourceColumn = sourceColumn; param.SourceVersion = DataRowVersion.Current; return param; } /// /// Creates an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type /// and DataRowVersion.Current type. /// /// The name of the parameter. /// One of the values. /// Source column for a parameter in the . /// The object. public IDbDataParameter Parameter( string parameterName, DbType dbType, string sourceColumn) { IDbDataParameter param = Parameter(ParameterDirection.Input, parameterName, dbType); param.SourceColumn = sourceColumn; param.SourceVersion = DataRowVersion.Current; return param; } /// /// Creates an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type /// and DataRowVersion.Current type. /// /// The name of the parameter. /// One of the values. /// Size of the parameter. /// Source column for a parameter in the . /// Version of data to use for a parameter in the . /// The object. public IDbDataParameter Parameter( string parameterName, DbType dbType, int size, string sourceColumn, DataRowVersion dataRowVersion) { IDbDataParameter param = Parameter(ParameterDirection.Input, parameterName, dbType, size); param.SourceColumn = sourceColumn; param.SourceVersion = dataRowVersion; return param; } /// /// Creates an input parameter to the . /// /// /// The method creates a parameter with the /// ParameterDirection.Input type /// and DataRowVersion.Current type. /// /// The name of the parameter. /// One of the values. /// Source column for a parameter in the . /// Version of data to use for a parameter in the . /// The object. public IDbDataParameter Parameter( string parameterName, DbType dbType, string sourceColumn, DataRowVersion dataRowVersion) { IDbDataParameter param = Parameter(ParameterDirection.Input, parameterName, dbType); param.SourceColumn = sourceColumn; param.SourceVersion = dataRowVersion; return param; } #endregion #region SetCommand /// /// Specifies the action that command is supposed to perform, i.e. Select, Insert, Update, Delete. /// It is used in Execute methods of the class to identify command instance /// to be used. /// enum CommandAction { Select, Insert, Update, Delete } private bool _executed; private bool _prepared; private IDbDataParameter[] _selectCommandParameters; private IDbDataParameter[] _insertCommandParameters; private IDbDataParameter[] _updateCommandParameters; private IDbDataParameter[] _deleteCommandParameters; private void SetCommand(CommandAction commandAction, IDbCommand command) { switch (commandAction) { case CommandAction.Select: _selectCommand = command; break; case CommandAction.Insert: _insertCommand = command; break; case CommandAction.Update: _updateCommand = command; break; case CommandAction.Delete: _deleteCommand = command; break; } } private IDbCommand GetCommand(CommandAction commandAction) { switch (commandAction) { default: case CommandAction.Select: return SelectCommand; case CommandAction.Insert: return InsertCommand; case CommandAction.Update: return UpdateCommand; case CommandAction.Delete: return DeleteCommand; } } private void SetCommandParameters(CommandAction commandAction, IDbDataParameter[] commandParameters) { switch (commandAction) { case CommandAction.Select: _selectCommandParameters = commandParameters; break; case CommandAction.Insert: _insertCommandParameters = commandParameters; break; case CommandAction.Update: _updateCommandParameters = commandParameters; break; case CommandAction.Delete: _deleteCommandParameters = commandParameters; break; } } private IDbDataParameter[] GetCommandParameters(CommandAction commandAction) { switch (commandAction) { default: case CommandAction.Select: return _selectCommandParameters; case CommandAction.Insert: return _insertCommandParameters; case CommandAction.Update: return _updateCommandParameters; case CommandAction.Delete: return _deleteCommandParameters; } } private DbManager SetCommand( CommandAction commandAction, CommandType commandType, string commandText, params IDbDataParameter[] commandParameters) { if (_executed) { _executed = false; _prepared = false; } PrepareCommand(commandAction, commandType, commandText, commandParameters); return this; } private DbManager SetSpCommand( CommandAction commandAction, string spName, bool openNewConnectionToDiscoverParameters, params object[] parameterValues) { return SetCommand( commandAction, CommandType.StoredProcedure, spName, CreateSpParameters(spName, parameterValues, openNewConnectionToDiscoverParameters)); } private DbManager SetSpCommand( CommandAction commandAction, string spName, params object[] parameterValues) { return SetCommand( commandAction, CommandType.StoredProcedure, spName, CreateSpParameters(spName, parameterValues, Configuration.OpenNewConnectionToDiscoverParameters)); } #region Select /// /// Creates a SQL statement. /// /// The command text to execute. /// Current instance. public DbManager SetCommand( string commandText) { return SetCommand(CommandAction.Select, CommandType.Text, commandText, null); } /// /// Creates a SQL statement. /// /// The (stored procedure, text, etc.) /// The command text to execute. /// Current instance. public DbManager SetCommand( CommandType commandType, string commandText) { return SetCommand(CommandAction.Select, commandType, commandText, null); } /// /// Creates a SQL statement. /// /// /// The method can be used to create the INSERT, UPDATE, and DELETE SQL statements. /// /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetCommand( string commandText, params IDbDataParameter[] commandParameters) { return SetCommand(CommandAction.Select, CommandType.Text, commandText, commandParameters); } /// /// Creates a SQL statement. /// /// The (stored procedure, text, etc.) /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetCommand( CommandType commandType, string commandText, params IDbDataParameter[] commandParameters) { return SetCommand(CommandAction.Select, commandType, commandText, commandParameters); } /// /// Creates a command to be executed as a stored procedure using the provided parameter values. /// /// /// The method queries the database to discover the parameters for the stored procedure /// (the first time each stored procedure is called), /// and assign the values based on parameter order. /// /// The name of the stored procedure /// An array of objects to be assigned as the input values of the stored procedure /// Current instance. public DbManager SetSpCommand( string spName, params object[] parameterValues) { return SetSpCommand(CommandAction.Select, spName, parameterValues); } public DbManager SetSpCommand( string spName, bool openNewConnectionToDiscoverParameters, params object[] parameterValues) { return SetSpCommand(CommandAction.Select, spName, openNewConnectionToDiscoverParameters, parameterValues); } public DbManager SetCommand(SqlQuery sql, params IDbDataParameter[] commandParameters) { StringBuilder sb = new StringBuilder(); DataProvider.CreateSqlProvider().BuildSql(sql, sb, 0, 0); string command = sb.ToString(); #if DEBUG string info = string.Format("{0} {1}\n{2}", DataProvider.Name, ConfigurationString, command); if (commandParameters != null && commandParameters.Length > 0) foreach (IDbDataParameter p in commandParameters) info += string.Format("\n{0}\t{1}", p.ParameterName, p.Value); Debug.WriteLineIf(TraceSwitch.TraceInfo, info, TraceSwitch.DisplayName); #endif return SetCommand(command, commandParameters); } #endregion #region Insert /// /// Creates an Insert SQL statement. /// /// /// The method can be used to create the INSERT, UPDATE, and DELETE SQL statements. /// /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetInsertCommand( string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Insert, CommandType.Text, commandText, commandParameters); } /// /// Creates an Insert SQL statement. /// /// The (stored procedure, text, etc.) /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetInsertCommand( CommandType commandType, string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Insert, commandType, commandText, commandParameters); } /// /// Creates an Insert command to be executed as a stored procedure using the provided parameter values. /// /// /// The method queries the database to discover the parameters for the stored procedure /// (the first time each stored procedure is called), /// and assign the values based on parameter order. /// /// The name of the stored procedure /// An array of objects to be assigned as the input values of the stored procedure /// Current instance. public DbManager SetInsertSpCommand( string spName, params object[] parameterValues) { return SetSpCommand(CommandAction.Insert, spName, parameterValues); } #endregion #region Update /// /// Creates an Update SQL statement. /// /// /// The method can be used to create the INSERT, UPDATE, and DELETE SQL statements. /// /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetUpdateCommand( string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Update, CommandType.Text, commandText, commandParameters); } /// /// Creates an Update SQL statement. /// /// The (stored procedure, text, etc.) /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetUpdateCommand( CommandType commandType, string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Update, commandType, commandText, commandParameters); } /// /// Creates an Update command to be executed as a stored procedure using the provided parameter values. /// /// /// The method queries the database to discover the parameters for the stored procedure /// (the first time each stored procedure is called), /// and assign the values based on parameter order. /// /// The name of the stored procedure /// An array of objects to be assigned as the input values of the stored procedure /// Current instance. public DbManager SetUpdateSpCommand( string spName, params object[] parameterValues) { return SetSpCommand(CommandAction.Update, spName, parameterValues); } #endregion #region Delete /// /// Creates a Delete SQL statement. /// /// /// The method can be used to create the INSERT, UPDATE, and DELETE SQL statements. /// /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetDeleteCommand( string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Delete, CommandType.Text, commandText, commandParameters); } /// /// Creates a Delete SQL statement. /// /// The (stored procedure, text, etc.) /// The command text to execute. /// An array of parameters used to executes the command. /// Current instance. public DbManager SetDeleteCommand( CommandType commandType, string commandText, params IDbDataParameter[] commandParameters) { return SetCommand( CommandAction.Delete, commandType, commandText, commandParameters); } /// /// Creates a Delete command to be executed as a stored procedure using the provided parameter values. /// /// /// The method queries the database to discover the parameters for the stored procedure /// (the first time each stored procedure is called), /// and assign the values based on parameter order. /// /// The name of the stored procedure /// An array of objects to be assigned as the input values of the stored procedure /// Current instance. public DbManager SetDeleteSpCommand( string spName, params object[] parameterValues) { return SetSpCommand(CommandAction.Delete, spName, parameterValues); } #endregion #endregion #region Prepare private void PrepareCommand( CommandAction commandAction, CommandType commandType, string commandText, IDbDataParameter[] commandParameters) { DataProvider.PrepareCommand(ref commandType, ref commandText, ref commandParameters); IDbCommand command = GetCommand(commandAction, commandType, commandText); SetCommand (commandAction, command); SetCommandParameters(commandAction, commandParameters); if (commandParameters != null) { AttachParameters(command, commandParameters); } } /// /// Prepares a command for execution. /// /// Current instance. public DbManager Prepare() { IDbCommand command = GetCommand(CommandAction.Select); if (InitParameters(CommandAction.Select) == false) { ExecuteOperation(OperationType.PrepareCommand, command.Prepare); } _prepared = true; return this; } bool InitParameters(CommandAction commandAction) { bool prepare = false; IDbDataParameter[] commandParameters = GetCommandParameters(commandAction); if (commandParameters != null) { foreach (IDbDataParameter p in commandParameters) { // This mysterious line of code required to fix a bug in MsSql. // It forces parameter's filed 'MetaType' to be set. // Same for p.Size = p.Size below. // p.DbType = p.DbType; if (p.Value is string) { int len = ((string)p.Value).Length; if (p.Size < len) { p.Size = len; prepare = true; } else p.Size = p.Size; } else if (p.Value is DBNull) { p.Size = 1; } else if (p.Value is byte[]) { int len = ((byte[])p.Value).Length; if (p.Size < len) { p.Size = len; prepare = true; } else p.Size = p.Size; } else if (p.Value is char[]) { int len = ((char[])p.Value).Length; if (p.Size < len) { p.Size = len; prepare = true; } else p.Size = p.Size; } else if (p.Value is decimal) { SqlDecimal d = (decimal)p.Value; if (p.Precision < d.Precision) { p.Precision = d.Precision; prepare = true; } else p.Precision = p.Precision; if (p.Scale < d.Scale) { p.Scale = d.Scale; prepare = true; } else p.Scale = p.Scale; } } // Re-prepare command to avoid truncation. // if (prepare) { IDbCommand command = GetCommand(commandAction); AttachParameters(command, commandParameters); command.Prepare(); } } return prepare; } #endregion #region ExecuteForEach /// /// Executes a SQL statement for a given collection of objects and /// returns the number of rows affected. /// /// /// The method prepares the object /// and calls the method for each item of the list. /// /// /// The list of objects used to execute the command. /// The number of rows affected by the command. public int ExecuteForEach(ICollection collection) { int rowsTotal = 0; if (collection != null && collection.Count != 0) { bool initParameters = true; foreach (object o in collection) { if (initParameters) { initParameters = false; IDbDataParameter[] parameters = GetCommandParameters(CommandAction.Select); if (parameters == null || parameters.Length == 0) { parameters = CreateParameters(o); SetCommandParameters(CommandAction.Select, parameters); AttachParameters(SelectCommand, parameters); Prepare(); } } AssignParameterValues(o); int rows = ExecuteNonQueryInternal(); if (rows > 0) rowsTotal += rows; } } return rowsTotal; } /// /// Executes a SQL statement for a given collection of objects and /// returns the number of rows affected. /// /// /// The method prepares the object /// and calls the method for each item of the list. /// /// /// The list of objects used to execute the command. /// The number of rows affected by the command. public int ExecuteForEach(ICollection collection) { int rowsTotal = 0; if (collection != null && collection.Count != 0) { bool initParameters = true; foreach (T o in collection) { if (initParameters) { initParameters = false; IDbDataParameter[] parameters = GetCommandParameters(CommandAction.Select); if (parameters == null || parameters.Length == 0) { parameters = CreateParameters(o); SetCommandParameters(CommandAction.Select, parameters); AttachParameters(SelectCommand, parameters); Prepare(); } } AssignParameterValues(o); int rows = ExecuteNonQueryInternal(); if (rows > 0) rowsTotal += rows; } } return rowsTotal; } public int ExecuteForEach(int maxBatchSize, IEnumerable collection) { ObjectMapper om = _mappingSchema.GetObjectMapper(typeof(T)); List mms = new List(); foreach (MemberMapper mm in om) { string name = _dataProvider.Convert(mm.Name, ConvertType.NameToParameter).ToString(); if (Command.Parameters.Contains(name)) mms.Add(mm); } return ExecuteForEach(collection, mms.ToArray(), maxBatchSize, delegate(T obj) { return CreateParameters(obj); }); } public delegate IDbDataParameter[] ParameterProvider(T obj); internal int ExecuteForEach(IEnumerable collection, MemberMapper[] members, int maxBatchSize, ParameterProvider getParameters) { if (collection == null) return 0; int maxRows = Math.Max( Math.Min( Math.Max( members.Length == 0? 1000 : _dataProvider.MaxParameters / members.Length, members.Length), maxBatchSize), 1); string baseSql = SelectCommand.CommandText; string paramName = _dataProvider.Convert(".", ConvertType.NameToQueryParameter).ToString(); int rowsTotal = 0; int nRows = 0; bool initParameters = true; bool saveCanRaseEvent = _canRaiseEvents; _canRaiseEvents = false; StringBuilder sb = new StringBuilder(); List rowSql = new List(maxRows); IDbDataParameter[] baseParameters = null; List parameters = new List(); foreach (T obj in collection) { if (initParameters) { initParameters = false; baseParameters = getParameters(obj); if (maxRows != 1) { int n = 0; foreach (IDbDataParameter p in baseParameters) n += p.ParameterName.Length + 3 - "{0}".Length + _dataProvider.EndOfSql.Length; maxRows = Math.Max(1, Math.Min(maxRows, _dataProvider.MaxBatchSize / (baseSql.Length + n))); } if (maxRows != 1) baseSql += _dataProvider.EndOfSql; } bool isSet; if (rowSql.Count < maxRows) { isSet = false; Converter c1 = delegate(IDbDataParameter p) { return p.ParameterName + nRows; }; Converter c2 = delegate(IDbDataParameter p) { return p.ParameterName; }; sb .Append("\n") .AppendFormat( baseSql, Array.ConvertAll( baseParameters, baseParameters.Length > 0 && baseParameters[0].ParameterName != paramName? c1 : c2)); rowSql.Add(sb.Length); for (int i = 0; i < members.Length; i++) { object value = members[i].GetValue(obj); parameters.Add(Parameter(baseParameters[i].ParameterName + nRows, value ?? DBNull.Value)); } } else { isSet = true; for (int i = 0, n = nRows * members.Length; i < members.Length; i++) { object value = members[i].GetValue(obj); parameters[n + i].Value = value == null || members[i].MapMemberInfo.Nullable && _mappingSchema.IsNull(value)? DBNull.Value: value; } } nRows++; if (nRows >= maxRows) { if (isSet == false) { SetCommand(sb.ToString(), parameters.ToArray()); Prepare(); } else { InitParameters(CommandAction.Select); } int n = ExecuteNonQueryInternal(); if (n > 0) rowsTotal += n; nRows = 0; } } if (nRows > 0) { if (rowSql.Count >= maxRows) { int nps = nRows * members.Length; parameters.RemoveRange(nps, parameters.Count - nps); sb.Length = rowSql[nRows - 1]; } SetCommand(sb.ToString(), parameters.ToArray()); Prepare(); int n = ExecuteNonQueryInternal(); if (n > 0) rowsTotal += n; } _canRaiseEvents = saveCanRaseEvent; return rowsTotal; } /// /// Executes a SQL statement for the and /// returns the number of rows affected. /// /// /// The method prepares the object /// and calls the method for each item /// of the . /// /// /// An instance of the class to execute the command. /// The number of rows affected by the command. public int ExecuteForEach(DataTable table) { int rowsTotal = 0; if (table != null && table.Rows.Count != 0) { IDbDataParameter[] parameters = GetCommandParameters(CommandAction.Select); if (parameters == null || parameters.Length == 0) { parameters = CreateParameters(table.Rows[0]); SetCommandParameters(CommandAction.Select, parameters); AttachParameters(SelectCommand, parameters); Prepare(); } foreach (DataRow dr in table.Rows) { AssignParameterValues(dr); int rows = ExecuteNonQueryInternal(); if (rows > 0) rowsTotal += rows; } } return rowsTotal; } /// /// Executes a SQL statement for the first table of the /// and returns the number of rows affected. /// /// /// The method prepares the object /// and calls the method for each item of the first table. /// /// /// An instance of the class to execute the command. /// The number of rows affected by the command. public int ExecuteForEach(DataSet dataSet) { return ExecuteForEach(dataSet.Tables[0]); } /// /// Executes a SQL statement for the specified table of the /// and returns the number of rows affected. /// /// /// The method prepares the object /// and calls the method for each item of the first table. /// /// /// An instance of the class to execute the command. /// The table name or index. /// name/index. /// The number of rows affected by the command. public int ExecuteForEach(DataSet dataSet, NameOrIndexParameter nameOrIndex) { return nameOrIndex.ByName ? ExecuteForEach(dataSet.Tables[nameOrIndex.Name]) : ExecuteForEach(dataSet.Tables[nameOrIndex.Index]); } #endregion #region ExecuteNonQuery /// /// Executes a SQL statement and returns the number of rows affected. /// /// /// The method can be used to execute the INSERT, UPDATE, and DELETE SQL statements. /// /// /// The number of rows affected by the command. public int ExecuteNonQuery() { if (_prepared) InitParameters(CommandAction.Select); return ExecuteNonQueryInternal(); } /// /// Executes a SQL statement and returns the number of rows affected. /// /// /// The method can be used to execute the INSERT, UPDATE, and DELETE SQL statements. /// /// Name of a to map return value. /// An to map from command parameters. /// The number of rows affected by the command. public int ExecuteNonQuery( string returnValueMember, object obj) { int rowsAffected = ExecuteNonQuery(); MapOutputParameters(returnValueMember, obj); return rowsAffected; } /// /// Executes a SQL statement and returns the number of rows affected. /// /// /// The method can be used to execute the INSERT, UPDATE, and DELETE SQL statements. /// /// An to map from command parameters. /// The number of rows affected by the command. public int ExecuteNonQuery(object obj) { int rowsAffected = ExecuteNonQuery(); MapOutputParameters(null, obj); return rowsAffected; } /// /// Executes a SQL statement and returns the number of rows affected. /// /// /// The method can be used to execute the INSERT, UPDATE, and DELETE SQL statements. /// /// Name of a to map return value. /// An array of to map /// from command parameters. /// The number of rows affected by the command. public int ExecuteNonQuery( string returnValueMember, params object[] objects) { int rowsAffected = ExecuteNonQuery(); MapOutputParameters(returnValueMember, objects); return rowsAffected; } /// /// Executes a SQL statement and returns the number of rows affected. /// /// /// The method can be used to execute the INSERT, UPDATE, and DELETE SQL statements. /// /// An array of to map /// from command parameters. /// The number of rows affected by the command. public int ExecuteNonQuery(params object[] objects) { int rowsAffected = ExecuteNonQuery(); MapOutputParameters(null, objects); return rowsAffected; } #endregion #region ExecuteScalar /// /// Executes the query, and returns the first column of the first row /// in the resultset returned by the query. Extra columns or rows are /// ignored. /// /// The first column of the first row in the resultset. /// public object ExecuteScalar() { if (_prepared) InitParameters(CommandAction.Select); using (IDataReader rd = ExecuteReaderInternal(CommandBehavior.Default)) return rd.Read() && rd.FieldCount > 0 ? rd.GetValue(0) : null; } /// /// Executes the query, and returns the value with specified scalar /// source type. /// /// The method used to return the scalar /// value. /// /// /// ScalarSourceType /// Return value /// /// /// DataReader /// The first column of the first row in the resultset. /// /// /// /// OutputParameter /// The value of the first output or input/output /// parameter returned. /// /// /// ReturnValue /// The value of the "return value" parameter returned. /// /// /// /// AffectedRows /// The number of rows affected. /// /// /// /// public object ExecuteScalar(ScalarSourceType sourceType) { return ExecuteScalar(sourceType, new NameOrIndexParameter()); } /// /// Executes the query, and returns the value with specified scalar /// source type. /// /// The method used to return the scalar value. /// The column name/index or output parameter name/index. /// /// /// ScalarSourceType /// Return value /// /// /// DataReader /// The column with specified name or at specified index /// of the first row in the resultset. /// /// /// OutputParameter /// The value of the output or input/output parameter /// returned with specified name or at specified index. /// /// /// ReturnValue /// The value of the "return value" parameter returned. /// The index parameter is ignored. /// /// /// AffectedRows /// The number of rows affected. The index parameter is /// ignored. /// /// /// public object ExecuteScalar(ScalarSourceType sourceType, NameOrIndexParameter nameOrIndex) { if (_prepared) InitParameters(CommandAction.Select); switch (sourceType) { case ScalarSourceType.DataReader: using (IDataReader reader = ExecuteReaderInternal()) if (reader.Read()) return reader.GetValue(nameOrIndex.ByName ? reader.GetOrdinal(nameOrIndex.Name) : nameOrIndex.Index); break; case ScalarSourceType.OutputParameter: ExecuteNonQueryInternal(); if (nameOrIndex.ByName) { string name = (string)_dataProvider.Convert(nameOrIndex.Name, ConvertType.NameToParameter); return Parameter(name).Value; } int index = nameOrIndex.Index; foreach (IDataParameter p in SelectCommand.Parameters) { // Skip the return value parameter. // if (p.Direction == ParameterDirection.ReturnValue) continue; if (0 == index) return p.Value; --index; } break; case ScalarSourceType.ReturnValue: ExecuteNonQueryInternal(); foreach (IDataParameter p in SelectCommand.Parameters) if (p.Direction == ParameterDirection.ReturnValue) return p.Value; break; case ScalarSourceType.AffectedRows: return ExecuteNonQueryInternal(); default: throw new InvalidEnumArgumentException("sourceType", (int)sourceType, typeof(ScalarSourceType)); } return null; } /// /// Executes the query, and returns the first column of the first row /// in the resultset returned by the query. Extra columns or rows are /// ignored. /// /// /// The first column of the first row in the resultset. /// public T ExecuteScalar() { return (T)_mappingSchema.ConvertChangeType(ExecuteScalar(), typeof(T)); } /// /// Executes the query, and returns the value with specified scalar /// source type. /// /// The method used to return the scalar /// value. /// /// /// ScalarSourceType /// Return value /// /// /// DataReader /// The first column of the first row in the resultset. /// /// /// /// OutputParameter /// The value of the first output or input/output /// parameter returned. /// /// /// ReturnValue /// The value of the "return value" parameter returned. /// /// /// /// AffectedRows /// The number of rows affected. /// /// /// /// public T ExecuteScalar(ScalarSourceType sourceType) { return ExecuteScalar(sourceType, new NameOrIndexParameter()); } /// /// Executes the query, and returns the value with specified scalar /// source type. /// /// The method used to return the scalar value. /// The column name/index or output parameter name/index. /// /// /// ScalarSourceType /// Return value /// /// /// DataReader /// The column with specified name or at specified index /// of the first row in the resultset. /// /// /// OutputParameter /// The value of the output or input/output parameter /// returned with specified name or at specified index. /// /// /// ReturnValue /// The value of the "return value" parameter returned. /// The index parameter is ignored. /// /// /// AffectedRows /// The number of rows affected. The index parameter is /// ignored. /// /// /// public T ExecuteScalar(ScalarSourceType sourceType, NameOrIndexParameter nameOrIndex) { return (T)_mappingSchema.ConvertChangeType(ExecuteScalar(sourceType, nameOrIndex), typeof(T)); } #endregion #region ExecuteScalarList /// /// Executes the query, and returns the array list of values of the /// specified column of the every row in the resultset returned by the /// query. Other columns are ignored. /// /// The array to fill in. /// The column name/index or output parameter name/index. /// The type of the each element. /// Array list of values of the specified column of the every /// row in the resultset. public IList ExecuteScalarList( IList list, Type type, NameOrIndexParameter nameOrIndex) { if (list == null) list = new ArrayList(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToScalarList(dr, nameOrIndex, list, type); } } /// /// Executes the query, and returns the array list of values of first /// column of the every row in the resultset returned by the query. /// Other columns are ignored. /// /// The array to fill in. /// The type of the each element. /// Array list of values of first column of the every row in /// the resultset. public IList ExecuteScalarList(IList list, Type type) { if (list == null) list = new ArrayList(); return ExecuteScalarList(list, type, 0); } /// /// Executes the query, and returns the array list of values of the /// specified column of the every row in the resultset returned by the /// query. Other columns are ignored. /// /// The column name/index. /// The type of the each element. /// Array list of values of the specified column of the every /// row in the resultset. public ArrayList ExecuteScalarList(Type type, NameOrIndexParameter nameOrIndex) { ArrayList list = new ArrayList(); ExecuteScalarList(list, type, nameOrIndex); return list; } /// /// Executes the query, and returns the array list of values of first /// column of the every row in the resultset returned by the query. /// Other columns are ignored. /// /// The type of the each element. /// Array list of values of first column of the every row in /// the resultset. public ArrayList ExecuteScalarList(Type type) { ArrayList list = new ArrayList(); ExecuteScalarList(list, type, 0); return list; } /// /// Executes the query, and returns the array list of values of the /// specified column of the every row in the resultset returned by the /// query. Other columns are ignored. /// /// The array to fill in. /// The column name/index or output parameter /// name/index. /// The type of the each element. /// Array list of values of the specified column of the every /// row in the resultset. public IList ExecuteScalarList( IList list, NameOrIndexParameter nameOrIndex) { if (list == null) list = new List(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToScalarList(dr, nameOrIndex, list); } } /// /// Executes the query, and returns the array list of values of first /// column of the every row in the resultset returned by the query. /// Other columns are ignored. /// /// The array to fill in. /// The type of the each element. /// Array list of values of first column of the every row in /// the resultset. public IList ExecuteScalarList(IList list) { return ExecuteScalarList(list, 0); } /// /// Executes the query, and returns the array list of values of the /// specified column of the every row in the resultset returned by the /// query. Other columns are ignored. /// /// The column name/index or output parameter name/index. /// The type of the each element. /// Array list of values of the specified column of the every /// row in the resultset. public List ExecuteScalarList(NameOrIndexParameter nameOrIndex) { List list = new List(); ExecuteScalarList(list, nameOrIndex); return list; } /// /// Executes the query, and returns the list of values of first /// column of the every row in the resultset returned by the query. /// Other columns are ignored. /// /// The type of the each element. /// Array list of values of first column of the every row in /// the resultset. public List ExecuteScalarList() { List list = new List(); ExecuteScalarList(list, 0); return list; } #endregion #region ExecuteScalarDictionary /// /// Executes the query, and returns the dictionary. /// The keys are loaded from a column specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The dictionary to add values. ///The column name/index to load keys. ///The key type. ///The column name/index to load values. ///The value type. ///The loaded dictionary. public IDictionary ExecuteScalarDictionary( IDictionary dic, NameOrIndexParameter keyField, Type keyFieldType, NameOrIndexParameter valueField, Type valueFieldType) { if (dic == null) dic = new Hashtable(); if (_prepared) InitParameters(CommandAction.Select); //object nullValue = _mappingSchema.GetNullValue(type); if (keyField.ByName && keyField.Name.Length > 0 && keyField.Name[0] == '@') keyField = keyField.Name.Substring(1); using (IDataReader dr = ExecuteReaderInternal()) { if (dr.Read()) { int keyIndex = keyField.ByName ? dr.GetOrdinal(keyField.Name) : keyField.Index; int valueIndex = valueField.ByName ? dr.GetOrdinal(valueField.Name) : valueField.Index; do { object value = dr[valueIndex]; object key = dr[keyIndex]; if (key == null || key.GetType() != keyFieldType) key = key is DBNull ? null : _mappingSchema.ConvertChangeType(key, keyFieldType); if (value == null || value.GetType() != valueFieldType) value = value is DBNull ? null : _mappingSchema.ConvertChangeType(value, valueFieldType); dic.Add(key, value); } while (dr.Read()); } } return dic; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from a column specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The column name/index to load keys. ///The key type. ///The column name/index to load values. ///The value type. ///The loaded dictionary. public Hashtable ExecuteScalarDictionary( NameOrIndexParameter keyField, Type keyFieldType, NameOrIndexParameter valueField, Type valueFieldType) { Hashtable table = new Hashtable(); ExecuteScalarDictionary(table, keyField, keyFieldType, valueField, valueFieldType); return table; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from a column specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The key type. ///The value type. ///The dictionary to add values. ///The column name/index to load keys. ///The column name/index to load values. ///The loaded dictionary. public IDictionary ExecuteScalarDictionary( IDictionary dic, NameOrIndexParameter keyField, NameOrIndexParameter valueField) { if (dic == null) dic = new Dictionary(); if (_prepared) InitParameters(CommandAction.Select); //object nullValue = _mappingSchema.GetNullValue(type); Type keyFieldType = typeof(K); Type valueFieldType = typeof(T); using (IDataReader dr = ExecuteReaderInternal()) { if (dr.Read()) { int keyIndex = keyField.ByName? dr.GetOrdinal(keyField.Name): keyField.Index; int valueIndex = valueField.ByName? dr.GetOrdinal(valueField.Name): valueField.Index; do { object value = dr[valueIndex]; object key = dr[keyIndex]; if (key == null || key.GetType() != keyFieldType) key = key is DBNull ? null : _mappingSchema.ConvertChangeType(key, keyFieldType); if (value == null || value.GetType() != valueFieldType) value = value is DBNull ? null : _mappingSchema.ConvertChangeType(value, valueFieldType); dic.Add((K)key, (T)value); } while (dr.Read()); } } return dic; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from a column specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The key type. ///The value type. ///The column name/index to load keys. ///The column name/index to load values. ///The loaded dictionary. public Dictionary ExecuteScalarDictionary( NameOrIndexParameter keyField, NameOrIndexParameter valueField) { Dictionary dic = new Dictionary(); ExecuteScalarDictionary(dic, keyField, valueField); return dic; } #endregion #region ExecuteScalarDictionary (Index) /// /// Executes the query, and returns the dictionary. /// The keys are loaded from columns specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The dictionary to add values. ///The of the key columns. ///The column name/index to load values. ///The value type. ///The loaded dictionary. public IDictionary ExecuteScalarDictionary( IDictionary dic, MapIndex index, NameOrIndexParameter valueField, Type valueFieldType) { if (dic == null) dic = new Hashtable(); if (_prepared) InitParameters(CommandAction.Select); //object nullValue = _mappingSchema.GetNullValue(type); using (IDataReader dr = ExecuteReaderInternal()) { if (dr.Read()) { int valueIndex = valueField.ByName ? dr.GetOrdinal(valueField.Name) : valueField.Index; int[] keyIndex = new int[index.Fields.Length]; for (int i = 0; i < keyIndex.Length; i++) keyIndex[i] = index.Fields[i].ByName ? dr.GetOrdinal(index.Fields[i].Name) : index.Fields[i].Index; do { object value = dr[valueIndex]; if (value == null || value.GetType() != valueFieldType) value = value is DBNull ? null : _mappingSchema.ConvertChangeType(value, valueFieldType); object[] key = new object[keyIndex.Length]; for (int i = 0; i < keyIndex.Length; i++) key[i] = dr[keyIndex[i]]; dic.Add(new CompoundValue(key), value); } while (dr.Read()); } } return dic; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from columns specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The of the key columns. ///The column name/index to load values. ///The value type. ///The loaded dictionary. public Hashtable ExecuteScalarDictionary( MapIndex index, NameOrIndexParameter valueField, Type valueFieldType) { Hashtable table = new Hashtable(); ExecuteScalarDictionary(table, index, valueField, valueFieldType); return table; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from columns specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The value type. ///The dictionary to add values. ///The of the key columns. ///The column name/index to load values. ///The loaded dictionary. public IDictionary ExecuteScalarDictionary( IDictionary dic, MapIndex index, NameOrIndexParameter valueField) { if (dic == null) dic = new Dictionary(); if (_prepared) InitParameters(CommandAction.Select); //object nullValue = _mappingSchema.GetNullValue(type); Type valueFieldType = typeof(T); using (IDataReader dr = ExecuteReaderInternal()) { if (dr.Read()) { int valueIndex = valueField.ByName ? dr.GetOrdinal(valueField.Name) : valueField.Index; int[] keyIndex = new int[index.Fields.Length]; for (int i = 0; i < keyIndex.Length; i++) keyIndex[i] = index.Fields[i].ByName ? dr.GetOrdinal(index.Fields[i].Name) : index.Fields[i].Index; do { object value = dr[valueIndex]; if (value == null || value.GetType() != valueFieldType) value = value is DBNull ? null : _mappingSchema.ConvertChangeType(value, valueFieldType); object[] key = new object[keyIndex.Length]; for (int i = 0; i < keyIndex.Length; i++) key[i] = dr[keyIndex[i]]; dic.Add(new CompoundValue(key), (T)value); } while (dr.Read()); } } return dic; } /// /// Executes the query, and returns the dictionary. /// The keys are loaded from columns specified by and /// values are loaded from a column specified by . /// Other columns are ignored. /// ///The value type. ///The of the key columns. ///The column name/index to load values. ///The loaded dictionary. public Dictionary ExecuteScalarDictionary( MapIndex index, NameOrIndexParameter valueField) { Dictionary dic = new Dictionary(); ExecuteScalarDictionary(dic, index, valueField); return dic; } #endregion #region ExecuteReader /// /// Executes the command and builds an . /// /// An instance of the class. public IDataReader ExecuteReader() { if (_prepared) InitParameters(CommandAction.Select); return ExecuteReaderInternal(); } /// /// Executes the command and builds an . /// /// One of the values. /// An instance of the class. public IDataReader ExecuteReader(CommandBehavior commandBehavior) { if (_prepared) InitParameters(CommandAction.Select); return ExecuteReaderInternal(commandBehavior); } #endregion #region ExecuteDataSet /// /// Executes a SQL statement using the provided parameters. /// /// /// See the method /// to find an example. /// /// The . public DataSet ExecuteDataSet() { return ExecuteDataSet(null, 0, 0, "Table"); } /// /// Executes a SQL statement using the provided parameters. /// /// /// See the method /// to find an example. /// /// The input object. /// The . public DataSet ExecuteDataSet( DataSet dataSet) { return ExecuteDataSet(dataSet, 0, 0, "Table"); } /// /// Executes a SQL statement using the provided parameters. /// /// /// See the method /// to find an example. /// /// The name or index of the populating table. /// The . public DataSet ExecuteDataSet( NameOrIndexParameter table) { return ExecuteDataSet(null, 0, 0, table); } /// /// Executes a SQL statement using the provided parameters. /// /// The object to populate. /// The name or index of the populating table. /// The . public DataSet ExecuteDataSet( DataSet dataSet, NameOrIndexParameter table) { return ExecuteDataSet(dataSet, 0, 0, table); } /// /// Executes a SQL statement using the provided parameters. /// /// The object to populate. /// The name or index of the populating table. /// The zero-based record number to start with. /// The maximum number of records to retrieve. /// The . public DataSet ExecuteDataSet( DataSet dataSet, int startRecord, int maxRecords, NameOrIndexParameter table) { if (_prepared) InitParameters(CommandAction.Select); if (dataSet == null) dataSet = new DataSet(); DbDataAdapter da = _dataProvider.CreateDataAdapterObject(); ((IDbDataAdapter)da).SelectCommand = SelectCommand; ExecuteOperation(OperationType.Fill, delegate { if (table.ByName) da.Fill(dataSet, startRecord, maxRecords, table.Name); else da.Fill(startRecord, maxRecords, dataSet.Tables[table.Index]); }); return dataSet; } #endregion #region ExecuteDataTable /// /// Executes a SQL statement using the provided parameters. /// /// The . public DataTable ExecuteDataTable() { return ExecuteDataTable(null); } /// /// Executes a SQL statement using the provided parameters. /// /// The object to populate. /// The . public DataTable ExecuteDataTable(DataTable dataTable) { if (_prepared) InitParameters(CommandAction.Select); if (dataTable == null) dataTable = new DataTable(); DbDataAdapter da = _dataProvider.CreateDataAdapterObject(); ((IDbDataAdapter)da).SelectCommand = SelectCommand; ExecuteOperation(OperationType.Fill, delegate { da.Fill(dataTable); }); return dataTable; } /// Adds or refreshes rows in a /// to match those in the data source starting at the specified record /// and retrieving up to the specified maximum number of records. /// /// The zero-based record number to start with. /// The maximum number of records to retrieve. /// The objects /// to fill from the data source. public void ExecuteDataTables( int startRecord, int maxRecords, params DataTable[] tableList) { if (tableList == null || tableList.Length == 0) return; if (_prepared) InitParameters(CommandAction.Select); DbDataAdapter da = _dataProvider.CreateDataAdapterObject(); ((IDbDataAdapter)da).SelectCommand = SelectCommand; ExecuteOperation(OperationType.Fill, delegate { da.Fill(startRecord, maxRecords, tableList); }); } /// Adds or refreshes rows in a /// to match those in the data source starting at the specified record /// and retrieving up to the specified maximum number of records. /// /// The objects /// to fill from the data source. public void ExecuteDataTables(params DataTable[] tableList) { ExecuteDataTables(0, 0, tableList); } #endregion #region ExecuteObject /// /// Executes a SQL statement and maps resultset to an object. /// /// An object to populate. /// The System.Type of the object. /// Additional parameters passed to object constructor through . /// A business object. private object ExecuteObjectInternal(object entity, Type type, object[] parameters) { if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal(/*CommandBehavior.SingleRow*/)) // Sybase provider does not support this flag. { while (dr.Read()) { return entity == null? _mappingSchema.MapDataReaderToObject(dr, type, parameters): _mappingSchema.MapDataReaderToObject(dr, entity, parameters); } return null; } } /// /// Executes a SQL statement and maps resultset to an object. /// /// An object to populate. /// A business object. public object ExecuteObject(object entity) { if (null == entity) throw new ArgumentNullException("entity"); return ExecuteObjectInternal(entity, entity.GetType(), null); } /// /// Executes a SQL statement and maps resultset to an object. /// /// An object to populate. /// Additional parameters passed to object constructor through . /// A business object. public object ExecuteObject(object entity, params object[] parameters) { if (null == entity) throw new ArgumentNullException("entity"); return ExecuteObjectInternal(entity, entity.GetType(), parameters); } /// /// Executes a SQL statement and maps resultset to an object. /// /// Type of an object. /// A business object. public object ExecuteObject(Type type) { return ExecuteObjectInternal(null, type, null); } /// /// Executes a SQL statement and maps resultset to an object. /// /// Type of an object. /// Additional parameters passed to object constructor through . /// A business object. public object ExecuteObject(Type type, params object[] parameters) { return ExecuteObjectInternal(null, type, parameters); } /// /// Executes a SQL statement and maps resultset to an object. /// /// Type of an object. /// A business object. public T ExecuteObject() { return (T)ExecuteObjectInternal(null, typeof(T), null); } /// /// Executes a SQL statement and maps resultset to an object. /// /// Type of an object. /// Additional parameters passed to object constructor through . /// A business object. public T ExecuteObject(params object[] parameters) { return (T)ExecuteObjectInternal(null, typeof(T), parameters); } #endregion #region ExecuteList private IList ExecuteListInternal(IList list, Type type, params object[] parameters) { if (list == null) list = new ArrayList(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToList(dr, list, type, parameters); } } private void ExecuteListInternal(IList list, params object[] parameters) { if (list == null) list = new List(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { _mappingSchema.MapDataReaderToList(dr, list, parameters); } } /// /// Executes the query, and returns an array of business entities using the provided parameters. /// /// Type of the business object. /// An array of business objects. public ArrayList ExecuteList(Type type) { ArrayList arrayList = new ArrayList(); ExecuteListInternal(arrayList, type, null); return arrayList; } /// /// Executes the query, and returns an array of business entities. /// /// Type of an object. /// Populated list of mapped business objects. public List ExecuteList() { List list = new List(); ExecuteListInternal(list, null); return list; } /// /// Executes the query, and returns an array of business entities using the provided parameters. /// /// Type of the business object. /// Additional parameters passed to object constructor through . /// An array of business objects. public ArrayList ExecuteList(Type type, params object[] parameters) { ArrayList arrayList = new ArrayList(); ExecuteListInternal(arrayList, type, parameters); return arrayList; } /// /// Executes the query, and returns an array of business entities. /// /// Type of an object. /// Additional parameters passed to object constructor through . /// Populated list of mapped business objects. public List ExecuteList(params object[] parameters) { List list = new List(); ExecuteListInternal(list, parameters); return list; } /// /// Executes the query, and returns an array of business entities. /// /// The list of mapped business objects to populate. /// Type of an object. /// Populated list of mapped business objects. public IList ExecuteList(IList list, Type type) { return ExecuteListInternal(list, type, null); } /// /// Executes the query, and returns an array of business entities. /// /// Type of an object. /// The list of mapped business objects to populate. /// Populated list of mapped business objects. public IList ExecuteList(IList list) { ExecuteListInternal(list, null); return list; } /// /// Executes the query, and returns an array of business entities. /// /// The list of mapped business objects to populate. /// Type of an object. /// Additional parameters passed to object constructor through . /// Populated list of mapped business objects. public IList ExecuteList(IList list, Type type, params object[] parameters) { return ExecuteListInternal(list, type, parameters); } /// /// Executes the query, and returns an array of business entities. /// /// Type of an object. /// The list of mapped business objects to populate. /// Additional parameters passed to object constructor through . /// Populated list of mapped business objects. public IList ExecuteList(IList list, params object[] parameters) { ExecuteListInternal(list, parameters); return list; } /// /// Executes the query, and returns an array of business entities. /// /// Type of a list. /// Type of an object. /// The list of mapped business objects to populate. /// Additional parameters passed to object constructor through . /// Populated list of mapped business objects. public L ExecuteList(L list, params object[] parameters) where L : IList { ExecuteListInternal(list, typeof(T), parameters); return list; } /// /// Executes the query, and returns an array of business entities. /// /// Type of a list. /// Type of an object. /// Additional parameters passed to object constructor through . /// Populated list of mapped business objects. public L ExecuteList(params object[] parameters) where L : IList, new() { L list = new L(); ExecuteListInternal(list, typeof(T), parameters); return list; } #endregion #region ExecuteDictionary /// /// Executes the query, and returns the of business entities /// using the provided parameters. /// /// /// The field name or index that is used as a key to populate . /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the class. public Hashtable ExecuteDictionary( NameOrIndexParameter keyField, Type keyFieldType, params object[] parameters) { Hashtable hash = new Hashtable(); ExecuteDictionary(hash, keyField, keyFieldType, parameters); return hash; } /// /// Executes the query, and returns the of business entities. /// /// /// A dictionary of mapped business objects to populate. /// The field name or index that is used as a key to populate . /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the . public IDictionary ExecuteDictionary( IDictionary dictionary, NameOrIndexParameter keyField, Type type, params object[] parameters) { if (dictionary == null) dictionary = new Hashtable(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToDictionary(dr, dictionary, keyField, type, parameters); } } /// /// Executes the query, and returns a dictionary of business entities. /// /// Key's type. /// Value's type. /// The field name or index that is used as a key to populate the dictionary. /// Any additional parameters passed to the constructor with parameter. /// An instance of the dictionary. public Dictionary ExecuteDictionary( NameOrIndexParameter keyField, params object[] parameters) { Dictionary dictionary = new Dictionary(); ExecuteDictionary(dictionary, keyField, typeof(TValue), parameters); return dictionary; } /// /// Executes the query, and returns the of business entities. /// /// A dictionary of mapped business objects to populate. /// The field name or index that is used as a key to populate . /// Any additional parameters passed to the constructor with parameter. /// An instance of the . public IDictionary ExecuteDictionary( IDictionary dictionary, NameOrIndexParameter keyField, params object[] parameters) { return ExecuteDictionary(dictionary, keyField, typeof(TValue), parameters); } /// /// Executes the query, and returns the of business entities. /// /// A dictionary of mapped business objects to populate. /// The field name or index that is used as a key to populate . /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the . public IDictionary ExecuteDictionary( IDictionary dictionary, NameOrIndexParameter keyField, Type destObjectType, params object[] parameters) { if (dictionary == null) dictionary = new Dictionary(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToDictionary( dr, dictionary, keyField, destObjectType, parameters); } } #endregion #region ExecuteDictionary (Index) /// /// Executes the query, and returns the of business entities /// using the provided parameters. /// /// /// Dictionary key fields. /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the class. public Hashtable ExecuteDictionary( MapIndex index, Type type, params object[] parameters) { Hashtable hash = new Hashtable(); ExecuteDictionary(hash, index, type, parameters); return hash; } /// /// Executes the query, and returns the of business entities. /// /// /// A dictionary of mapped business objects to populate. /// Dictionary key fields. /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the . public IDictionary ExecuteDictionary( IDictionary dictionary, MapIndex index, Type type, params object[] parameters) { if (dictionary == null) dictionary = new Hashtable(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToDictionary(dr, dictionary, index, type, parameters); } } /// /// Executes the query, and returns a dictionary of business entities. /// /// Value's type. /// Dictionary key fields. /// Any additional parameters passed to the constructor with parameter. /// An instance of the dictionary. public Dictionary ExecuteDictionary( MapIndex index, params object[] parameters) { Dictionary dictionary = new Dictionary(); ExecuteDictionary(dictionary, index, typeof(TValue), parameters); return dictionary; } /// /// Executes the query, and returns a dictionary of business entities. /// /// Value's type. /// A dictionary of mapped business objects to populate. /// Dictionary key fields. /// Any additional parameters passed to the constructor with parameter. /// An instance of the dictionary. public IDictionary ExecuteDictionary( IDictionary dictionary, MapIndex index, params object[] parameters) { return ExecuteDictionary(dictionary, index, typeof(TValue), parameters); } /// /// Executes the query, and returns a dictionary of business entities. /// /// Value's type. /// A dictionary of mapped business objects to populate. /// Dictionary key fields. /// Business object type. /// Any additional parameters passed to the constructor with parameter. /// An instance of the dictionary. public IDictionary ExecuteDictionary( IDictionary dictionary, MapIndex index, Type destObjectType, params object[] parameters) { if (dictionary == null) dictionary = new Dictionary(); if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { return _mappingSchema.MapDataReaderToDictionary( dr, dictionary, index, destObjectType, parameters); } } #endregion #region ExecuteResultSet /// /// Executes the query, and returns multiple results. /// /// Array of to populate. /// The populated . public MapResultSet[] ExecuteResultSet(params MapResultSet[] resultSets) { if (_prepared) InitParameters(CommandAction.Select); using (IDataReader dr = ExecuteReaderInternal()) { _mappingSchema.MapDataReaderToResultSet(dr, resultSets); } return resultSets; } /// /// Executes the query, and returns multiple results. /// /// The type of the master business object. /// Array of to populate. /// The populated . public MapResultSet[] ExecuteResultSet( Type masterType, params MapNextResult[] nextResults) { return ExecuteResultSet(_mappingSchema.ConvertToResultSet(masterType, nextResults)); } /// /// Executes the query, and returns multiple results. /// /// The type of the master business object. /// Array of to populate. /// The populated . public MapResultSet[] ExecuteResultSet(params MapNextResult[] nextResults) { return ExecuteResultSet(_mappingSchema.ConvertToResultSet(typeof(T), nextResults)); } #endregion #region Update private DbDataAdapter CreateDataAdapter() { DbDataAdapter da = _dataProvider.CreateDataAdapterObject(); if (_insertCommand != null) ((IDbDataAdapter)da).InsertCommand = InsertCommand; if (_updateCommand != null) ((IDbDataAdapter)da).UpdateCommand = UpdateCommand; if (_deleteCommand != null) ((IDbDataAdapter)da).DeleteCommand = DeleteCommand; return da; } /// /// Calls the corresponding INSERT, UPDATE, or DELETE statements for each inserted, updated, or /// deleted row in the specified . /// /// The used to update the data source. /// The number of rows successfully updated from the . public int Update(DataSet dataSet) { return Update(dataSet, "Table"); } /// /// Calls the corresponding INSERT, UPDATE, or DELETE statements for each inserted, updated, or /// deleted row in the with the specified name. /// /// The used to update the data source. /// The name or index of the source table to use for table mapping. /// The number of rows successfully updated from the . public int Update( DataSet dataSet, NameOrIndexParameter table) { if (dataSet == null) throw new ArgumentNullException( "dataSet", Resources.DbManager_CannotUpdateNullDataset); DbDataAdapter da = CreateDataAdapter(); return ExecuteOperation(OperationType.Update, delegate { return (table.ByName) ? da.Update(dataSet, table.Name) : da.Update(dataSet.Tables[table.Index]); }); } /// /// Calls the corresponding INSERT, UPDATE, or DELETE statements for /// each inserted, updated, or deleted row in the specified /// . /// /// The name or index of the source table to /// use for table mapping. /// The number of rows successfully updated from the /// . public int Update(DataTable dataTable) { if (dataTable == null) throw new ArgumentNullException( "dataTable", Resources.DbManager_CannotUpdateNullDataTable); return ExecuteOperation(OperationType.Update, delegate { return CreateDataAdapter().Update(dataTable); }); } #endregion #region ExecuteOperation private void ExecuteOperation(OperationType operationType, Action operation) { try { OnBeforeOperation(operationType); operation(); OnAfterOperation (operationType); } catch (Exception ex) { HandleOperationException(operationType, ex); throw; } } private T ExecuteOperation(OperationType operationType, Func operation) { T res = default(T); try { OnBeforeOperation(operationType); res = operation(); OnAfterOperation (operationType); } catch (Exception ex) { if (res is IDisposable) ((IDisposable)res).Dispose(); HandleOperationException(operationType, ex); throw; } return res; } private void HandleOperationException(OperationType op, Exception ex) { DataException dex = new DataException(this, ex); Debug.WriteLineIf(TraceSwitch.TraceError, string.Format( "Operation '{0}' throws exception '{1}'", op, dex), TraceSwitch.DisplayName); OnOperationException(op, dex); } #endregion #region IDisposable interface /// /// Releases the unmanaged resources used by the and /// optionally releases the managed resources. /// /// /// This method is called by the public method /// and the Finalize method. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (disposing) Close(); base.Dispose(disposing); } #endregion } }