1

データベースに複数の 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;
4

2 に答える 2

7

OK、この答えはトピックから外れていますが、私はしなければなりません:サービスブローカーで発火して忘れないでください。begin-send-end メッセージ パターンには、エラー応答のトラブルシューティングができないことから、データベースがオフラインになることまで、多くの問題があります。後者は SSB (SQL Service Broker) のバグによるものですが、私はそれが発生するのを見てきました。これは fire and forget メッセージ パターンが原因です。

ああ、もう1つ:DBArtisanが何であるかはわかりませんが、ASCIIメッセージが有効であると見なされ、message_body列をvarchar(max)にキャストすることを意味します。それだけです。

私の投稿はすでに大きいので、XML エンコーディングと SSB についても少し詳しく説明します。おそらくご存じのとおり、メッセージ タイプ[SAPP_MSG_MessageType]を として宣言すると、SSB は XML メッセージ検証を提供しますVALIDATION = WELL_FORMED_XML。しかし、ASCII と UNICODE はどちらも有効な XML エンコーディングであり、どちらも SSB でサポートされています。メッセージN'<someTag>somecontent</someTag>'と も送信でき'<someTag>somecontent</someTag>'ます。どちらも有効な XML スニペットです。<?xml version="1.0" encoding="utf-8"?>またはNのように、エンコーディングを宣言する明示的な XML 処理命令を追加することもできます<?xml version="1.0" encoding="utf-16"?>ただし、 Nを宣言するなど、それらを不一致にするリスクがあります<?xml version="1.0" encoding="utf-8"?>、これは実際には無効な XML です (宣言されたエンコーディングがドキュメントのエンコーディングと一致しないため)。このような非常に微妙でトラブルシューティングが難しいあらゆる種類の問題に遭遇する可能性があります。これは、ターゲット サービスがメッセージを拒否し、XML 検証応答でダイアログを失敗させる可能性がある問題の完璧な例です。

私の実践 (私は MS の SQL Service Broekr チームのメンバーの 1 人でした) で、問題を回避する最善の方法は、送信された (@msg) を保持する変数を varchar や nvarchar ではなく xml 型として宣言することであることがわかりました。これにより、すべての問題が処理され、XMLでの BOM の必要性と存在にも適切に対処できます。これは、渡された C# パラメーターにも適用されます。最適な一致は、SqlXml型および/またはSystem.Data.SqlDbType.Xml列挙値を使用することです。

また、キューの受信側 (ターゲット キューを読み取るアクティブ化されたプロシージャまたはプロセス) では、メッセージ本文を varchar/nvarchar ではなく、XML 型にキャストする必要があります。この件については、受信中にキャストしないようにしてください。XMLエラー処理がアクティベーションと相互作用する方法のため、受信後にのみキャストしてください。

于 2009-07-09T23:48:11.667 に答える
5

それだけかどうかはわかりませんが、nvarchar リテラルを使用しているのに varchar 変数に代入しているようです...

于 2009-07-09T23:20:46.573 に答える