private ConnectionData CreateConnectionData(DataTransaction transaction)
        {
            ConnectionData data = null;

            try
            {
                if (transaction != null)
                {
                    data = new ConnectionData(transaction.InnerTransaction);
                }
                else
                {
                    data = new ConnectionData(CreateConnectionBase(ConnectionString));
                }

                PrepareConnectionCore(data);
                return(data);
            } catch
            {
                if (data != null)
                {
                    data.Dispose();
                }

                throw;
            };
        }
        /// <summary>Executes a command and returns the results as a <see cref="DataSet"/>.</summary>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="command">The command to execute.</param>
        /// <returns>The results as a <see cref="DataSet"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="command"/> is <see langword="null"/>.</exception>
        public DataSet ExecuteDataSet(DataCommand command, DataTransaction transaction)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            using (var conn = CreateConnectionData(transaction))
            {
                return(ExecuteDataSetCore(conn, command));
            };
        }
        /// <summary>Fills a data set with the results of a command.</summary>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="ds">The data set to fill.</param>
        /// <param name="tables">The tables to use for storing the results.</param>
        /// <param name="command">The command to execute.</param>
        /// <exception cref="ArgumentNullException"><paramref name="ds"/> or <paramref name="command"/> is <see langword="null"/>.</exception>
        public void FillDataSet(DataCommand command, DataSet ds, string[] tables, DataTransaction transaction)
        {
            if (ds == null)
            {
                throw new ArgumentNullException("ds");
            }
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            using (var conn = CreateConnectionData(transaction))
            {
                FillDataSetCore(conn, ds, command, tables);
            };
        }
        /// <summary>Executes a command and returns a data reader with the results.</summary>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="command">The command to execute.</param>
        /// <returns>A <see cref="DbDataReader"/> containing the results.  The reader may be empty but it will
        /// never be <see langword="null"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="command"/> is <see langword="null"/>.</exception>
        /// <seealso cref="O:ExecuteQueryWithResult{T}"/>
        /// <seealso cref="O:ExecuteQueryWithResults{T}"/>
        public DbDataReader ExecuteReader(DataCommand command, DataTransaction transaction)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            using (var conn = CreateConnectionData(transaction))
            {
                var dr = ExecuteReaderCore(conn, command);

                //The reader is now responsible for connection cleanup
                conn.Detach();

                return(dr);
            };
        }
        /// <summary>Updates a <see cref="DataSet"/>.</summary>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="insertCommand">Command to use for insertions.</param>
        /// <param name="deleteCommand">Command to use for deletions.</param>
        /// <param name="updateCommand">Command to use for updates.</param>
        /// <param name="ds"><see cref="DataSet"/> to use.</param>
        /// <param name="table">The table to use when updating the command.  If <see langword="null"/> or empty then the
        /// first table is used.</param>
        /// <remarks>
        /// To support transactions, precede this call with ExecuteScalar("begin transaction").  Failure to
        /// use transactions could cause failed updates to be partially applied.
        /// <para/>
        /// The command parameters can be <see langword="null"/> but the update will fail if the command is needed.
        /// </remarks>
        /// <exception cref="DBConcurrencyException">A concurrency error occurred.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="ds"/> is <see langword="null"/>.</exception>
        public void UpdateDataSet(DataCommand insertCommand, DataCommand deleteCommand,
                                  DataCommand updateCommand, DataSet ds, string table, DataTransaction transaction)
        {
            if (insertCommand == null)
            {
                throw new ArgumentNullException("insertCommand");
            }
            if (deleteCommand == null)
            {
                throw new ArgumentNullException("deleteCommand");
            }
            if (updateCommand == null)
            {
                throw new ArgumentNullException("updateCommand");
            }
            if (ds == null)
            {
                throw new ArgumentNullException("ds");
            }

            //Initialize table name as needed
            table = (table ?? "").Trim();
            if (String.IsNullOrEmpty(table) && (ds.Tables.Count > 0))
            {
                table = ds.Tables[0].TableName;
            }

            using (var conn = CreateConnectionData(transaction))
            {
                UpdateDataSetCore(conn, insertCommand, deleteCommand, updateCommand, ds, table);
            };
        }
 /// <summary>Fills a data set with the results of a command.</summary>
 /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
 /// <param name="ds">The data set to fill.</param>
 /// <param name="command">The command to execute.</param>
 /// <exception cref="ArgumentNullException"><paramref name="ds"/> or <paramref name="command"/> is <see langword="null"/>.</exception>
 public void FillDataSet(DataCommand command, DataSet ds, DataTransaction transaction)
 {
     FillDataSet(command, ds, null, transaction);
 }
        /// <summary>Executes a command and returns the first result.</summary>
        /// <typeparam name="T">The type of the value returned.</typeparam>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="command">The command to execute.</param>
        /// <returns>The first element from the result set.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="command"/> is <see langword="null"/>.</exception>
        public T ExecuteScalar <T>(DataCommand command, DataTransaction transaction)
        {
            var result = ExecuteScalar(command, transaction);

            return(((result != null) && (result != DBNull.Value)) ? (T)Convert.ChangeType(result, typeof(T)) : default(T));
        }
        /// <summary>Executes a command, parses the results and returns a strongly-typed array of objects.</summary>
        /// <typeparam name="TResult">The type of the objects to return.</typeparam>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="command">The command to execute.</param>
        /// <param name="converter">The method to use to convert the row to an object.</param>
        /// <param name="data">User-provided data to parse to the delegate.</param>
        /// <returns>An enumerable list containing the objects that were parsed.  The list will never be <see langword="null"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="command"/> or <paramref name="converter"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// This method combines the functionality of <see cref="O:ExecuteReader"/> with the standard code used to load data
        /// from a reader into a business object.  <paramref name="converter"/> is called once for each row to build the list
        /// of data objects to return.
        /// </remarks>
        /// <seealso cref="O:ExecuteQueryWithResult{TResult}"/>
        public IEnumerable <TResult> ExecuteQueryWithResults <TResult>(DataCommand command, Func <DbDataReader, Object, TResult> converter, object data, DataTransaction transaction)
        {
            if (converter == null)
            {
                throw new ArgumentNullException("converter");
            }

            var items = new List <TResult>();

            using (var dr = ExecuteReader(command, transaction))
            {
                while (dr.Read())
                {
                    items.Add(converter(dr, data));
                }
            };

            return(items);
        }
        /// <summary>Executes a command, parses the result and returns a strongly-typed object.</summary>
        /// <typeparam name="TResult">The type of the objects to return.</typeparam>
        /// <param name="transaction">The transaction to execute within.  If it is <see langword="null"/> then no transaction is used.</param>
        /// <param name="command">The command to execute.</param>
        /// <param name="converter">The method to convert the row to an object.</param>
        /// <param name="data">The data to pass to the converter.</param>
        /// <returns>An object containing the data that was parsed.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="command"/> or <paramref name="converter"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// This method combines the functionality of <see cref="O:ExecuteReader"/> with the standard code used to load data
        /// from a reader into a business object.  <paramref name="converter"/> is called once for each row to build the list
        /// of data objects to return.
        /// </remarks>
        /// <seealso cref="O:ExecuteQueryWithResults{TResult}"/>
        public TResult ExecuteQueryWithResult <TResult>(DataCommand command, Func <DbDataReader, object, TResult> converter, object data, DataTransaction transaction)
        {
            if (converter == null)
            {
                throw new ArgumentNullException("converter");
            }

            using (var dr = ExecuteReader(command, transaction))
            {
                if (dr.Read())
                {
                    return(converter(dr, data));
                }
            };

            return(default(TResult));
        }