服务代理激活输出"The message body may not be null",当关闭队列上的 XML 验证时



2014 MS SQL Server 上运行服务代理 从测试切换到实时正在生成一个新错误:

激活的进程"[dbo]"。usp_CalcPrice]"在队列"dbo"上运行。CalcPriceDataQueue"输出以下内容:"消息正文可能不为 NULL。 允许使用零长度的 UNICODE 或二进制字符串。

从测试版到实时版的区别在于 [dbo] 中使用的消息类型。[usp_CalcPrice] 不再具有验证 = XML 架构 XXXXXX,但为了性能,更改为验证 = 无。

我添加了一个表来转储存储过程 [dbo] 的内容。[usp_CalcPrice]从队列中接收,看起来很好,这样做:

  WHILE (1 = 1) 
  BEGIN -- Receive the next available message from the queue 
    WAITFOR ( 
             RECEIVE TOP(1)     
             @message_body = CAST(message_body AS XML),     
             @dialog = conversation_handle
        FROM [dbo].[CalcPriceDataQueue]), TIMEOUT 50    
        IF (@@ROWCOUNT = 0 OR @message_body IS NULL) 
        BEGIN 
            break
        END 
        ELSE 
        BEGIN 
            SET @XmlBody = CAST(@message_body AS Nvarchar(max))
            INSERT INTO dbo.SB_Tester (XmlBody)
            VALUES(@XmlBody)
            ...

在一个简单的测试中,队列获得 6-8k 个条目,在测试服务器上,它们在"没有时间"处理,没有错误,但在实时上,每个条目需要 2 - 5 秒,并且 Windows 事件查看器在 dbo 中每个条目(上面的一个)收到一个错误。SB_Tester,我在测试和实时队列中的每个条目中都得到了一个漂亮的 XML 条目。

附加信息:

@@Version: Microsoft SQL Server 2014 - 12.0.2254.0 (X64) 七月 25 2014 18:52:51 版权所有 (c) Microsoft公司 Windows NT 6.3 上的企业版(64 位)(内部版本 9600:)

它们被维护,因此版本始终相同。

发送到队列的代码:

DECLARE @MessageBody XML
SET @MessageBody = N'<Calc 
                        PartId="'           + @PartId +'"
                        CustomerId="'       + @CustId + '"
                        PriceRuleId="'      + @RuleId + '"
                        BaseSalesPrice="'   + @BaseSalesPrice + '"
                        CostPrice="'        + @CostPrice + '"
                        MinDB="'            + @MinDB + '"
                        IgnoreMinDB="'      + @IgnoreMinDB + '"
                        NoPriceRaising="'   + @NoPriceRaising + '"
                        Priority="'         + @Priority + '"
                        TargetPrice="'      + @TargetPrice + '"
                        ChangeType="'       + @ChangeType + '"
                        Change="'           + @Change + '"
                    />'
--PRINT CONVERT(Nvarchar(max), @MessageBody)
IF (@MessageBody IS NOT NULL)  
    BEGIN 
        DECLARE @Handle UNIQUEIDENTIFIER;   
        BEGIN DIALOG CONVERSATION @Handle
        FROM SERVICE [PriceCalcServiceSource]
        TO SERVICE   'PriceCalcServiceSink'
        ON CONTRACT [CalcPriceDataContract]
        WITH ENCRYPTION = OFF;   
        SEND ON CONVERSATION @Handle   
        MESSAGE TYPE [PriceData](@MessageBody);
    END

队列和消息创建:

CREATE MESSAGE TYPE [PriceData] VALIDATION = NONE
GO
CREATE CONTRACT [CalcPriceDataContract] ([PriceData] SENT BY INITIATOR)
GO
CREATE QUEUE [dbo].[CalcPriceDataQueue] WITH STATUS = ON ,
    RETENTION = OFF , 
    ACTIVATION (STATUS = ON , 
                PROCEDURE_NAME = [dbo].[usp_CalcPrice] , 
                MAX_QUEUE_READERS = 40 , 
                EXECUTE AS OWNER  ), 
    POISON_MESSAGE_HANDLING (STATUS = ON)  
    ON [PRIMARY] 
GO

在测试服务器上创建消息:

CREATE MESSAGE TYPE [PriceData]
VALIDATION = VALID_XML WITH SCHEMA COLLECTION dbo.PriceData

有人知道这个问题的原因吗?任何帮助都非常感谢:)

/格鲁

我参加聚会有点晚了,但我在服务代理方面遇到了同样的问题。当我们的大型机软件尝试将数据插入 SQL Server 数据库时,插入操作被取消,日志文件具有相同的消息。我从负责大型机的企业收到的建议是修改目标表上的触发器,以便在开始事务之前检查插入的信息是否存在。这是我的触发器现在的样子:

ALTER TRIGGER [dbo].[OnPedidoCompraInserted] ON [dbo].[PEDIDO_COMPRA] FOR INSERT
AS
BEGIN
    IF EXISTS (SELECT * FROM inserted) -- this is the verification he recommended me to add
    begin
        BEGIN TRANSACTION;
        DECLARE @ch UNIQUEIDENTIFIER
        DECLARE @messageBody NVARCHAR(MAX);
 
        BEGIN DIALOG CONVERSATION @ch
        FROM SERVICE [InitPedidoCompraService]
        TO SERVICE 'TargetPedidoCompraService'
        ON CONTRACT [http://ssb.csharp.at/PedidoCompraContract]
        WITH ENCRYPTION = OFF;
 
        -- Construct the request message
        SET @messageBody = (SELECT * from inserted FOR XML AUTO, ELEMENTS);
 
        -- Send the message to the TargetService
        ;SEND ON CONVERSATION @ch
        MESSAGE TYPE [http://ssb.csharp.at/RequestPedidoCompra] (@messageBody);
        COMMIT;
    END
end

我知道我迟到了,但我希望我将来能帮助别人。

相关内容

最新更新