public static async Task <AsyncDbDataReader <IDataReader> > ExecuteReaderAsync(this IDatasourceConnection connection, string commandText,
                                                                                       object parameters                   = null, bool joinTransaction = true,
                                                                                       CommandType commandType             = CommandType.Text, int commandTimeout = -1,
                                                                                       CommandBehavior behavior            = CommandBehavior.Default,
                                                                                       CancellationToken cancellationToken = default(CancellationToken))
        {
            IDbTransaction tx = null;

            if (joinTransaction)
            {
                tx = LocalTransaction.Current?.DbTransaction;
                if (tx != null && !ReferenceEquals(tx.Connection, connection.DbConnection))
                {
                    tx = null;
                }
            }

            IDbCommand cmd = connection.DbConnection.CreateCommand(commandText, commandType, commandTimeout, tx);

            if (parameters != null)
            {
                cmd.AddParametersWithValues(parameters);
            }

            IDataReader reader = await cmd.ExecuteReaderAsync(behavior, cancellationToken);

            return(new AsyncDbDataReader <IDataReader>(reader, cmd, null, x => x));
        }
        //
        // Higher-order utilities
        //

        public static async Task <int> ExecuteNonQueryAsync(this IDatasourceConnection connection, string commandText,
                                                            object parameters                   = null, bool joinTransaction = true,
                                                            CommandType commandType             = CommandType.Text, int commandTimeout = -1,
                                                            CancellationToken cancellationToken = default(CancellationToken))
        {
            IDbTransaction tx = null;

            if (joinTransaction)
            {
                tx = LocalTransaction.Current?.DbTransaction;
                if (tx != null && !ReferenceEquals(tx.Connection, connection.DbConnection))
                {
                    tx = null;
                }
            }

            using (IDbCommand cmd = connection.DbConnection.CreateCommand(commandText, commandType, commandTimeout, tx))
            {
                if (parameters != null)
                {
                    cmd.AddParametersWithValues(parameters);
                }

                return(await cmd.ExecuteNonQueryAsync(cancellationToken));
            }
        }
        public static async Task <AsyncDbDataReader <T> > ExecuteReaderAsync <T>(this IDatasourceConnection connection, string commandText,
                                                                                 object parameters                   = null, bool joinTransaction = true,
                                                                                 CommandType commandType             = CommandType.Text, int commandTimeout = -1,
                                                                                 CommandBehavior behavior            = CommandBehavior.Default,
                                                                                 CancellationToken cancellationToken = default(CancellationToken))
            where T : new()
        {
            IDbTransaction tx = null;

            if (joinTransaction)
            {
                tx = LocalTransaction.Current?.DbTransaction;
                if (tx != null && !ReferenceEquals(tx.Connection, connection.DbConnection))
                {
                    tx = null;
                }
            }

            IDbCommand  cmd    = null;
            IDataReader reader = null;

            try
            {
                cmd = connection.DbConnection.CreateCommand(commandText, commandType, commandTimeout, tx);
                if (parameters != null)
                {
                    cmd.AddParametersWithValues(parameters);
                }

                reader = await cmd.ExecuteReaderAsync(behavior, cancellationToken);

                return(new AsyncDbDataReader <T>(reader, cmd, null, ConvertByColumnNames <T>));
            }
            catch (Exception)
            {
                reader?.Dispose();
                cmd?.Dispose();
                throw;
            }
        }