public async Task <(bool, Message)> TryDequeueAsync()
        {
            const string sql = @"
delete
  from MessageQueue
  output deleted.Type, deleted.Payload, deleted.PublishedOnUTC
  where Id = (select top 1 Id
                from MessageQueue with (readpast)
                order by PublishedOnUTC)";

            using (IDatasourceConnection connection = await _datasource.GetConnectionAsync())
                using (AsyncDbDataReader <IDataReader> reader = await connection.ExecuteReaderAsync(sql))
                {
                    if (await reader.ReadAsync())
                    {
                        var ordinalOf = new
                        {
                            Type           = reader.DbReader.GetOrdinal("Type"),
                            Payload        = reader.DbReader.GetOrdinal("Payload"),
                            PublishedOnUTC = reader.DbReader.GetOrdinal("PublishedOnUTC")
                        };

                        var message = new Message
                        {
                            Payload        = await reader.Current.GetStream(ordinalOf.Payload).ReadFullyAndDisposeAsync(),
                            PublishedOnUTC = reader.Current.GetDateTime(ordinalOf.PublishedOnUTC),
                            Type           = reader.Current.GetString(ordinalOf.Type)
                        };

                        return(true, message);
                    }

                    return(false, null);
                }
        }
        //
        // 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 async Task EnqueueAsync(Message message)
        {
            const string sql = "insert into MessageQueue(Type, PublishedOnUTC, Payload) values(@Type, @PublishedOnUTC, @Payload)";

            using (IDatasourceConnection conn = await _datasource.GetConnectionAsync())
            {
                await conn.ExecuteNonQueryAsync(sql, new { message.Type, message.PublishedOnUTC, message.Payload });
            }
        }
        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;
            }
        }
        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));
        }
 public DeferredDisposingDatasourceConnection(IDatasourceConnection @delegate)
 {
     Delegate = @delegate;
 }