public async Task <bool> DeadletterMessageAsync(MessageBrokerContext context, TransactionContext transactionContext, string deadLetterReason, string deadLetterErrorDescription, CancellationToken cancellationToken)
        {
            ReceivedMessage msg = null;

            if (!context?.Container.TryGet(out msg) ?? false)
            {
                throw new ArgumentException($"Unable to deadletter message. No {nameof(ReceivedMessage)} contained in {nameof(context)}.", nameof(msg));
            }

            transactionContext.Container.TryGet <SqlConnection>(out var connection);
            transactionContext.Container.TryGet <SqlTransaction>(out var transaction);

            try
            {
                var edc = new EndDialogConversationCommand(connection,
                                                           msg.ConvHandle,
                                                           enableCleanup: _ssbOptions.CleanupOnEndConversation,
                                                           transaction: transaction);
                await edc.ExecuteAsync(cancellationToken);

                using var scope = _serviceFactory.CreateScope();
                var ssbSender     = scope.ServiceProvider.GetRequiredService <SqlServiceBrokerSender>();
                var bodyConverter = _bodyConverterFactory.CreateBodyConverter(_ssbOptions.MessageBodyType);

                _localReceiverDeliveryAttempts.TryGetValue(msg.ConvHandle, out var deliveryAttempts);

                var headers = new Dictionary <string, object>()
                {
                    [SSBMessageContext.ConversationHandle]  = msg.ConvHandle,
                    [SSBMessageContext.ServiceName]         = msg.ServiceName,
                    [MessageContext.FailureDescription]     = deadLetterErrorDescription,
                    [MessageContext.FailureDetails]         = deadLetterReason,
                    [MessageContext.InfrastructureType]     = SSBMessageContext.InfrastructureType,
                    [SSBMessageContext.MessageTypeName]     = ServicesMessageTypes.ChatterBrokeredMessageType,
                    [SSBMessageContext.ServiceContractName] = ServicesMessageTypes.ChatterServiceContract,
                    [MessageContext.ReceiveAttempts]        = deliveryAttempts
                };
                await ssbSender.Dispatch(new OutboundBrokeredMessage(context.BrokeredMessage.MessageId, msg.Body, headers, _options.DeadLetterQueuePath, bodyConverter), transactionContext);

                await transaction?.CommitAsync(cancellationToken);

                _localReceiverDeliveryAttempts.TryRemove(msg.ConvHandle, out var _);
                _logger.LogTrace($"Message deadlettered.");
                return(true);
            }
            finally
            {
                transaction?.Dispose();
                connection?.Dispose();
            }
        }
        public async Task <bool> AckMessageAsync(MessageBrokerContext context, TransactionContext transactionContext, CancellationToken cancellationToken)
        {
            ReceivedMessage msg = null;

            if (!context?.Container.TryGet(out msg) ?? false)
            {
                _logger.LogTrace($"No {nameof(ReceivedMessage)} contained in {nameof(context)}.");
            }

            transactionContext.Container.TryGet <SqlConnection>(out var connection);
            transactionContext.Container.TryGet <SqlTransaction>(out var transaction);

            try
            {
                if (msg != null)
                {
                    var edc = new EndDialogConversationCommand(connection,
                                                               msg.ConvHandle,
                                                               enableCleanup: _ssbOptions.CleanupOnEndConversation,
                                                               transaction: transaction);
                    await edc.ExecuteAsync(cancellationToken);

                    _localReceiverDeliveryAttempts.TryRemove(msg.ConvHandle, out var _);
                }
                else
                {
                    _logger.LogTrace($"Unable end dialog conversation during message acknowledgment. {nameof(msg)} is null.");
                }
                await transaction?.CommitAsync(cancellationToken);

                _logger.LogTrace("Message acknowledgment complete");
                return(true);
            }
            finally
            {
                transaction?.Dispose();
                connection?.Dispose();
            }
        }