private void handleMessage
            (BrokeredMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }


            // When the service is stopped we call the close method on the
            // topic.  The following guard statement is needed because there
            // can be a delay between calling close on the topic and it
            // stopping the message pump.

            if (ingressTopicSubscription != null &&
                !ingressTopicSubscription.IsClosed)
            {
                Trace.TraceInformation($"[{message.MessageId}] Received message");

                var dataModel
                    = new DataModelDbContext();

                try {
                    Trace.TraceInformation($"[{message.MessageId}] Processing message");


                    processMessageInServiceLayer(
                        dataModel,
                        message,
                        serviceCommandFactory
                        );
                    message.Complete();

                    // Note - The audit domain is a essentially a query domain it
                    //        records informations to allow querying for audit events
                    //        as such it does not trigger any events which is why
                    //        after completing the message there is not more processing
                    //        need to ensure that the message has been handled correctly/

                    Trace.TraceInformation($"[{message.MessageId}] Completed message");
                } catch (Exception e) {
                    Trace.TraceError($"[{message.MessageId}] Error - Message: {e.Message}, Stack trace: {e.StackTrace}");
                    throw;
                } finally {
                    dataModel.Dispose();
                }
            }
        }
        private static void processMessageInServiceLayer
            (DataModelDbContext dataModel
            , BrokeredMessage message
            , ServiceCommandFactory serviceCommandFactory)
        {
            if (dataModel == null)
            {
                throw new ArgumentNullException(nameof(dataModel));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (serviceCommandFactory == null)
            {
                throw new ArgumentNullException(nameof(serviceCommandFactory));
            }


            var messageId
                = Guid.Parse(message.MessageId);

            // If there is an exception between before the commit you do not
            // want to complete the message.  If there there is a problem
            // between the commit and the message being completed then we
            // have a message that will be processed twice so we take the
            // hit and just check to see if we have seen the message before
            // and if so just return and let the message be cleared of the
            // subscription.
            if (dataModel.HasSeenMessage(messageId))
            {
                return;
            }


            var transaction
                = dataModel
                  .Database
                  .BeginTransaction(IsolationLevel.Serializable);

            try {
                dataModel
                .AddMessageAsSeen(messageId);


                var serviceRequest
                    = new ServiceRequest(
                          dataModel
                          , Guid.Parse(message.CorrelationId)
                          , messageId
                          , TopicSourceName
                          , message.ContentType
                          , message.GetBody <string>()
                          , DateTime.Now
                          );


                // Because topics are heterogeneous we need to identify the
                // correct service command for the message. Different messages
                // have different handlers.
                //
                // It may be valid that we are not interested in auditing
                // certain messages in which case we need a default handler.
                serviceCommandFactory[message.ContentType]
                .Match(
                    just: serviceCommand => serviceCommand
                    , nothing: () => new UnhandledMessage()
                    )
                .Handle(serviceRequest);

                dataModel.SaveChanges();
                transaction.Commit();
            } finally {
                transaction.Dispose();
            }
        }