我正在使用以下方法在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中搜索该句柄,则它也不存在。我没有在任何地方积极结束对话。 为什么没有记录?
答案 0 :(得分:0)
经过一番忙碌之后,我找到了解决问题的方法。首先,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
然后,我需要修改接收代码,以处理以下事实:在调用结束对话时,队列中出现了额外的结束对话框消息:
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();
}
}
现在,它很好地工作了,我很可能会按照Dan Guzman的建议进行操作并参数化结束对话查询,并将其围绕在using查询中。
希望这可以帮助其他遇到问题的人。
Rob