Отсутствует дескриптор разговора в Service Broker - PullRequest
0 голосов
/ 28 декабря 2018

Я создаю диалог для своей очереди в Service Broker (SQL 2016), используя следующее:

BEGIN TRANSACTION

BEGIN DIALOG CONVERSATION @NotificationDialog 
FROM SERVICE ChangeNotifications 
TO SERVICE 'ChangeNotifications' 
ON CONTRACT [http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] 
WITH ENCRYPTION = OFF; 

-- Send the message 
-- 
SEND ON CONVERSATION @NotificationDialog  
MESSAGE TYPE [http://schemas.microsoft.com/SQL/Notifications/QueryNotification] (@Message)      

COMMIT TRANSACTION

Я получаю сообщение в службе Windows, используя следующий код:

using (SqlCommand cmd = new SqlCommand("WAITFOR ( RECEIVE * FROM dbo.NotificationsQueue);", cnn))
{
    cmd.CommandTimeout = 0;
    cnn.Open();

    // Execute the command - we will wait here until a new entry appears in the Notification Queue
    //
    SqlDataReader reader = cmd.ExecuteReader();

    // Get the message text from the reader
    //
    while (reader.Read())
    {
        // Get the message body text and convert into a legible format
        //
        messageText = reader.GetString(reader.GetOrdinal("message_body"));
        messtype = reader.GetString(reader.GetOrdinal("message_type_name"));
        convhandle = reader.GetGuid(reader.GetOrdinal("conversation_handle"));
    }

    reader.Close();
    reader = null;

    if (messtype == @"http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog" ||
        messtype == @"http://schemas.microsoft.com/SQL/ServiceBroker/Error" ||
        messtype == @"http://schemas.microsoft.com/SQL/Notifications/QueryNotification" )
    {
        var cmd2 = new SqlCommand("end conversation '" + convhandle.ToString() + "'", cnn);

        cmd2.ExecuteNonQuery();

        cmd2.Dispose();
    }
}

Когда код пытается выполнить окончание диалога, я получаю сообщение об ошибке «Дескриптор диалога не найден».Если я ищу sys.conversation_endpoints для дескриптора, он также не существует.Я нигде активно не заканчиваю разговор.Почему для этого нет записи?

1 Ответ

0 голосов
/ 22 января 2019

После недолгих раздумий я нашел решение своей проблемы.Прежде всего, стороне sql требовался конец разговора:

BEGIN TRANSACTION

BEGIN DIALOG CONVERSATION @NotificationDialog 
FROM SERVICE ChangeNotifications 
TO SERVICE 'ChangeNotifications' 
ON CONTRACT [http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] 
WITH ENCRYPTION = OFF; 

-- Send the message 
-- 
SEND ON CONVERSATION @NotificationDialog  
MESSAGE TYPE [http://schemas.microsoft.com/SQL/Notifications/QueryNotification] (@Message)      

-- ** Was missing from original code **
--
END CONVERSATION @NotificationDialog;   

COMMIT TRANSACTION

Затем мне нужно было изменить принимающий код для обработки того факта, что я получаю дополнительное сообщение End Dialog в очереди, когда я вызываю завершение разговора.:

using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MetricBroadcast.Properties.Settings.TargetConnectionString"].ToString()))
{
    string messtype = "";
    Guid convhandle = new Guid();

    cnn.Open();
    trans = cnn.BeginTransaction("queuetrans");

    // Create the command to monitor the Notifications Queue
    //
    using (SqlCommand cmd = new SqlCommand("WAITFOR ( RECEIVE * FROM dbo.NotificationsQueue);", cnn, trans))
    {
        cmd.CommandTimeout = 0;

        // Execute the command - we will wait here until a new entry appears in the Notification Queue
        //
        SqlDataReader reader = cmd.ExecuteReader();

        // Get the message text from the reader
        //
        while (reader.Read())
        {
            // Get the message body text and convert into a legible format
            //
            messtype = reader.GetString(reader.GetOrdinal("message_type_name"));
            convhandle = reader.GetGuid(reader.GetOrdinal("conversation_handle"));

            if (messtype == @"http://schemas.microsoft.com/SQL/Notifications/QueryNotification")
            {
                messageText = System.Text.UTF8Encoding.Unicode.GetString(reader.GetSqlBinary(reader.GetOrdinal("message_body")).Value);
            }
        }

        reader.Close();
        reader = null;


        if (messtype == @"http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog" ||
            messtype == @"http://schemas.microsoft.com/SQL/ServiceBroker/Error")
        {
            var cmd2 = new SqlCommand("end conversation '" + convhandle.ToString() + "'", cnn, trans);

            cmd2.ExecuteNonQuery();

            cmd2.Dispose();
        }

        trans.Commit();
    }
}

Теперь, когда все работает хорошо, я, вероятно, сделаю то, что предлагает Дан Гузман, и параметризирую запрос завершения разговора и окружу его запросом использования.

Надеюсь, это поможет кому-то ещевозникли проблемы.

Роб

...