Китайские иероглифы в сообщении SQL Service Broker - PullRequest
1 голос
/ 10 июля 2009

Я установил несколько очередей SQL Service Broker в базе данных, но раньше не сталкивался с этой проблемой. Сообщение, содержащее XML, преобразуется в то, что в основном выглядит как китайские иероглифы. Когда я проверяю переменную, в которой хранится XML, до помещения его в очередь сообщений, я вижу, что он написан на английском языке и хорошо сформирован в формате XML. Когда я выбираю из очереди, я получаю китайские иероглифы. Эти символы также получаются, когда я вытаскиваю из очереди внешнее приложение C #. Странно то, что если я просматриваю очередь с помощью DBArtisan, я вижу правильно сформированный XML.

Приведенный ниже XML при размещении в очереди преобразуется в следующие китайские иероглифы

<?xml version="1.0" ?>
<Message>
  <MachineName>The Super Duper Machine</MachineName>
  <CollectionName>snl0013d</CollectionName>
  <Action>Install</Action>
  <EntryDateTime>Jul  9 2009  4:47PM</EntryDateTime>
</Message>

㼼浸敶獲潩㵮ㄢ〮•㸿਍†††䴼獥慳敧ാ
 †††㰠慍档湩乥浡㹥桔⁥畓数⁲畄数⁲慍档湩㱥䴯捡楨敮慎敭ാ
 †††㰠潃汬捥楴湯慎敭猾汮〰㌱㱤䌯汯敬瑣潩乮浡㹥਍
 ††††䄼瑣潩㹮湉瑳污㱬䄯瑣潩㹮
 ਍††††䔼瑮祲慄整楔敭䨾汵†‹〲㤰†㨵〱䵐⼼湅牴䑹瑡呥浩㹥਍
†††⼼敍獳条㹥

Ниже приведен T-SQL, который я использую, чтобы поместить сообщение в очередь и выбрать его.

declare @dialog_handle uniqueidentifier
       ,@msg varchar(max)
       ,@collection_name varchar(30)

set @collection_name = 'snl0013d'

set @msg =
N'<?xml version="1.0" ?>
  <Message>
    <MachineName>' + 'The Super Duper Machine' + '</MachineName>
    <CollectionName>' + @collection_name + '</CollectionName>
    <Action>' + 'Install' + '</Action>
    <EntryDateTime>' + CAST(getdate() AS VARCHAR(100)) + '</EntryDateTime>
  </Message>'

select @msg

set @dialog_handle = NEWID()
begin dialog conversation @dialog_handle
    from service [SAPP_QUEUE_ResponseService]
    to service 'SAPP_QUEUE_SubmitService'
    on contract [SAPP_CONTRACT_Contract]
    with encryption = off;

send on conversation @dialog_handle
  message type [SAPP_MSG_MessageType]
(
    @msg
);
end conversation @dialog_handle 
with cleanup

select message_body
      ,conversation_handle
      ,CONVERT(nvarchar(max), message_body) as msg
  from SAPP_QUEUE_SubmitQueue;

Ответы [ 2 ]

7 голосов
/ 10 июля 2009

ОК, этот ответ не по теме, но я должен: пожалуйста, не делайте запускайте и забудьте с сервисным брокером. Шаблон сообщения begin-send-end имеет много проблем, начиная от невозможности устранения неполадок, связанных с ошибками, когда ваша база данных переводится в автономный режим. Последнее связано с ошибкой в ​​SSB (SQL Service Broker), но я видел, что это происходит, и это вызвано шаблоном сообщения «забыл и забыл».

Да, и еще одна вещь: я не знаю, что такое DBArtisan, но он видит ваше ASCII-сообщение действительным, то есть он переводит столбец message_body в varchar (max), вот и все.

И поскольку мой пост уже большой, позвольте мне немного углубиться в кодировку XML и SSB. Как вы, вероятно, знаете, SSB предлагает проверку сообщений XML, если вы объявляете тип сообщения [SAPP_MSG_MessageType] как VALIDATION = WELL_FORMED_XML. Но ASCII и UNICODE являются допустимыми кодировками XML и оба поддерживаются SSB. Вы можете отправить сообщение N '<someTag>somecontent</someTag>', а также '<someTag>somecontent</someTag>', оба являются допустимыми фрагментами XML. Вы также можете добавить явные инструкции по обработке XML, объявляющие кодировку, например <?xml version="1.0" encoding="utf-8"?> или N <?xml version="1.0" encoding="utf-16"?>. Однако вы рискуете не соответствовать им, например, объявив N <?xml version="1.0" encoding="utf-8"?>, что на самом деле является недопустимым XML (поскольку объявленная кодировка не соответствует кодировке документа). Вы можете столкнуться с очень тонкими и сложными проблемами, как эта. Это прекрасный пример проблемы, которая может привести к тому, что целевая служба отклонит сообщение и завершит работу с диалоговым окном с ответом проверки XML, который вы пропустите, потому что ... вы выполняете запрос на запуск:)

В своей практике (я был одним из членов команды SQL Service Broekr в MS) я обнаружил, что лучший способ избежать каких-либо проблем - объявить переменные, содержащие отправленный (@msg), тип xml , не varchar, ни nvarchar . Это решает все проблемы, а также правильно учитывает необходимость и наличие спецификации в вашем XML . Это также относится и к передаваемым параметрам C #, лучше всего использовать тип SqlXml и / или значение System.Data.SqlDbType.Xml .

Также на принимающей стороне очереди (ваша активированная процедура или процесс, который читает целевую очередь), вы должны преобразовать тело сообщения в тип XML, а не в varchar / nvarchar. И пока мы обсуждаем эту тему, убедитесь, что вы не разыграли во время получения, а только после получения, потому что обработка ошибок XML взаимодействует с активацией . * 1036. *

5 голосов
/ 10 июля 2009

Не знаю, так ли это, но я вижу, что вы используете литералы nvarchar, но присваиваете переменным varchar ...

...