public async Task ReceiveAsync_UsesTransaction()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle;", new { handle });

            // Act
            var transaction = await provider.BeginTransactionAsync();
            var beforeRollback = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue"));
            transaction.Rollback();
            var afterRollback = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue"));

            // Assert
            Assert.NotEmpty(beforeRollback);
            Assert.NotEmpty(afterRollback);
        }
        public async Task ReceiveAsync_RespectsPredicate_ConversationGroupId()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle1 = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle1;", new { handle1 });
            var handle2 = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle2;", new { handle2 });
            var groups = await connection.QueryAsync(
                "SELECT conversation_group_id FROM [TargetQueue] WITH (NOLOCK)");
            var group = groups.Last().conversation_group_id;

            // Act
            var receive = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue")
            {
                Predicate = (ConversationGroupId)group,
            });

            // Assert
            Assert.Equal(group, receive.Single().ConversationGroupId.Value);
        }
        public async Task ReceiveAsync_DecodesMessageBodyAsUnicode()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle (N'Hello');", new { handle });
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle ('Hello');", new { handle });

            // Act
            var receive = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue")
            {
            });

            // Assert
            Assert.Equal("Hello", receive.First().Body);
            Assert.NotEqual("Hello", receive.Last().Body);
        }
        public async Task ReceiveAsync_RespectsWaitFor()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle = await BeginDialogAsync();

            // Act
            var receive = provider.ReceiveAsync(new ReceiveArguments("TargetQueue")
            {
                WaitFor = MillisecondTimeout.Unlimited,
            });
            Thread.Sleep(1000);

            // Assert
            Assert.False(receive.IsCompleted);
        }
        public async Task ReceiveAsync_RespectsTop()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle;", new { handle });
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle;", new { handle });

            // Act
            var receive = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue")
            {
                Top = 1,
                WaitFor = TimeSpan.FromSeconds(5),
            });

            // Assert
            Assert.Equal(1, receive.Count());
        }
        public async Task ReceiveAsync_RespectsQueue()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider = new SqlServerServiceBroker(connection);
            var handle = await BeginDialogAsync();
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle;", new { handle });

            // Act
            var receive = await provider.ReceiveAsync(new ReceiveArguments("TargetQueue")
            {
            });

            // Assert
            Assert.True(receive.Any());
        }
        public async Task ReceiveAsync_ArgumentsCannotBeNull()
        {
            // Arrange
            var provider = new SqlServerServiceBroker(connection);

            // Act
            Func<Task> call = async () => await provider.ReceiveAsync(null);

            // Assert
            await Assert.ThrowsAsync<ArgumentNullException>("arguments", call);
        }
        public async Task GetConversationGroupAsync_UsesTransaction()
        {
            // Arrange
            await InitializeDatabaseAsync();
            var provider1 = new SqlServerServiceBroker(connection);
            var provider2 = new SqlServerServiceBroker(new SqlConnection(connection.ConnectionString));
            var handle = await BeginDialogAsync();
            IEnumerable<ReceivedMessage> beforeRollback;
            IEnumerable<ReceivedMessage> afterRollback;
            await connection.ExecuteAsync("SEND ON CONVERSATION @handle;", new { handle });

            // Act
            using (var transaction = await provider1.BeginTransactionAsync())
            {
                var arguments = new GetConversationGroupArguments("TargetQueue");
                var groupId = await provider1.GetConversationGroupAsync(arguments);
                var receiveArgs = new ReceiveArguments("TargetQueue")
                {
                    Predicate = groupId.Value,
                    WaitFor = TimeSpan.FromSeconds(1),
                };

                beforeRollback = await provider2.ReceiveAsync(receiveArgs);
                transaction.Rollback();
                afterRollback = await provider2.ReceiveAsync(receiveArgs);
            }

            // Assert
            Assert.Empty(beforeRollback);
            Assert.NotEmpty(afterRollback);
        }