SQL Server:在Service Broker中使用Schema Collection验证消息
这是我编写的一个手册中的一部分
--第一步:创建一个XML架构集合 --假设我们希望的XML数据格式如下(将它保存为OrderRequest.xml /* <?xml version="1.0"?> <OrderRequest OrderId="10248" CustomerID="ABCDEF" OrderDate="2010-1-25"> <OrderItems> <Item ProductId="1" UnitPrice="20.5" Quantity="6" /> <Item ProductId="2" UnitPrice="30" Quantity="6.8" /> </OrderItems> </OrderRequest> */ --使用xsd工具生成架构 >xsd OrderRequst.xml --创建架构集合 CREATE XML SCHEMA COLLECTION OrderRequestSchema AS N'<?xml version="1.0"?> <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="OrderRequest"> <xs:complexType> <xs:sequence> <xs:element name="OrderItems" minOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="Item" minOccurs="1" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="ProductId" type="xs:string" /> <xs:attribute name="UnitPrice" type="xs:string" /> <xs:attribute name="Quantity" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="OrderId" type="xs:string" /> <xs:attribute name="CustomerID" type="xs:string" /> <xs:attribute name="OrderDate" type="xs:string" /> </xs:complexType> </xs:element> <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element ref="OrderRequest" /> </xs:choice> </xs:complexType> </xs:element> </xs:schema>'; --这个Schema中我们定义了数据类型,并且我们规定item必须至少出现一次,也就是说一个订单必须至少有一个明细 --第二步:创建一个消息类型,使用该架构集合进行验证 CREATE MESSAGE TYPE [//Adventure-Works.com/OrderRequest] VALIDATION = VALID_XML WITH SCHEMA COLLECTION OrderRequestSchema ; --第三步:创建合约 CREATE CONTRACT [//AWDB/1DBSample/OrderContract] ([//Adventure-Works.com/OrderRequest] SENT BY INITIATOR ); GO --第四步:创建队列和服务 CREATE QUEUE InitOrderQueue CREATE QUEUE TargetOrderQueue CREATE SERVICE InitOrderService ON QUEUE InitOrderQueue([//AWDB/1DBSample/OrderContract]) CREATE SERVICE TargetOrderService ON QUEUE TargetOrderQueue([//AWDB/1DBSample/OrderContract]) --第五步:测试消息传输 DECLARE @InitDlgHandle UNIQUEIDENTIFIER;--这是会话的句柄 DECLARE @RequestMsg NVARCHAR(100); BEGIN TRANSACTION; BEGIN DIALOG @InitDlgHandle--BEGIN DIALOG语句会开始一个会话,并将会话的句柄赋予之前的变量 FROM SERVICE InitOrderService --FROM SERVICE是不要单引号的,直接引用对象。(为什么这样做?) TO SERVICE N'TargetOrderService' -- TO SERVICE则需要单引号 ON CONTRACT [//AWDB/1DBSample/OrderContract] WITH ENCRYPTION = OFF; --不做加密 SELECT @RequestMsg = N'<RequestMsg>Message for Target service.</RequestMsg>'; --这里用SET语句应该也是一样的吧 /*SEND ON CONVERSATION @InitDlgHandle MESSAGE TYPE [//AWDB/1DBSample/RequestMessage] (@RequestMsg); */ --如果这里不改,那么会报告一个错误,因为服务不接受这种消息 /* 消息 8431,级别 16,状态 1,第 18 行 消息类型 '//AWDB/1DBSample/RequestMessage' 不是服务约定的一部分。 */ SEND ON CONVERSATION @InitDlgHandle MESSAGE TYPE [//Adventure-Works.com/OrderRequest](@RequestMsg) SELECT @RequestMsg AS SentRequestMsg; --显示一下发送出去的消息 --请注意,我们的消息是不满足架构的,但这个代码执行是没有问题的 COMMIT TRANSACTION; GO SELECT * FROM InitOrderQueue SELECT * FROM TargetOrderQueue --通过查看两个队列中的消息,我们发现目标队列中并没有消息,而来源队列中则有一个类型为http://schemas.microsoft.com/SQL/ServiceBroker/Error的消息,什么意思呢?就是说发送失败了. --下面我们来读取这个消息看看什么内容 DECLARE @Msg NVARCHAR(1000); RECEIVE @Msg=message_body FROM InitOrderQueue; SELECT @Msg; --错误消息是下面这样的,意思就是说验证无法通过。 --<?xml version="1.0"?> -- <Error xmlns="http://schemas.microsoft.com/SQL/ServiceBroker/Error"> -- <Code>-9615</Code> -- <Description>A message of type '//Adventure-Works.com/OrderRequest' failed XML validation on the target service. XML Validation: Declaration not found for element 'RequestMsg'. Location: /*:RequestMsg[1] This occurred in the message with Conversation ID '2CEEFDE9-3E21-416E-B8FB-E731CF8FDA4C', Initiator: 1, and Message sequence number: 0. -- </Description> -- </Error>