首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调用由Service组成的存储过程

如何调用由Service组成的存储过程
EN

Stack Overflow用户
提问于 2017-10-17 07:17:13
回答 1查看 605关注 0票数 1

我不知道这个问题是否重复。如果这个问题是重复的,请给我链接。

我的问题是如何调用由BEGIN TRANSACTION & COMMIT TRANSACTION (Service )组成的2个存储过程。

我有两个存储过程,用来执行Service的一些操作。

这是包含BEGIN CONVERSATION的存储过程。

代码语言:javascript
复制
USE [EventCloud]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SendingMessage_Group_Id]
    @reference_id UNIQUEIDENTIFIER
AS
BEGIN
    DECLARE @ch UNIQUEIDENTIFIER
    DECLARE @conversation_group_id UNIQUEIDENTIFIER
    DECLARE @msg NVARCHAR(MAX)

    SET @conversation_group_id = @reference_id

    BEGIN TRY
        BEGIN TRANSACTION

            BEGIN DIALOG CONVERSATION @ch
                FROM SERVICE [InitiatorService]
                TO SERVICE 'TargetService'
                ON CONTRACT [http://ssb.csharp.at/SSB_Book/c03/HelloWorldContract]
                WITH RELATED_CONVERSATION_GROUP = @conversation_group_id,
                    ENCRYPTION = OFF

            SET @msg = '<HelloWorldRequest>1234</HelloWorldRequest>'

            ;SEND ON CONVERSATION @ch MESSAGE TYPE [http://ssb.csharp.at/SSB_Book/c03/RequestMessage]
            (
                @msg
            )

        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION
    END CATCH
END

下面的代码是TargetQueue的内部激活存储过程:

代码语言:javascript
复制
USE [EventCloud]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ProcessRequestMessage]
AS
BEGIN
    DECLARE @ch UNIQUEIDENTIFIER
    DECLARE @messagetypename NVARCHAR(256)
    DECLARE @messagebody XML
    DECLARE @responsemessage XML;
    DECLARE @errorcode INT
    DECLARE @errormessage NVARCHAR(3000);

    WHILE (1 = 1)
    BEGIN
        BEGIN TRY
            BEGIN TRANSACTION;
                WAITFOR(
                    RECEIVE TOP (1)
                        @ch = conversation_handle,
                        @messagetypename = message_type_name,
                        @messagebody = CAST(message_body AS XML)
                    FROM TargetQueue
                )

                IF (@@ROWCOUNT = 0)
                BEGIN
                    ROLLBACK TRANSACTION
                    BREAK
                END

                -- Process the requested message and send back to Initiator
                ELSE IF (@messagetypename = 'http://ssb.csharp.at/SSB_Book/c03/RequestMessage')
                BEGIN
                    -- Store the received request message in a table
                    INSERT INTO ProcessedMessages (ID, MessageBody, ServiceName, ProcessedDateTime)
                    VALUES (NEWID(), @messagebody, 'TargetService', GETDATE())

                    -- Construct the response message
                    SET @responsemessage =
                        '<HelloWorldResponse>' +
                            @messagebody.value('/HelloWorldRequest[1]', 'NVARCHAR(MAX)') +
                        '</HelloWorldResponse>';

                    -- Send the response message back to the initiating service
                    SEND ON CONVERSATION @ch MESSAGE TYPE [http://ssb.csharp.at/SSB_Book/c03/ResponseMessage]
                    (
                        @responsemessage
                    );

                    -- END the conversation on the target's side
                    END CONVERSATION @ch;
                END

                -- End the conversation if meet the message type
                IF (@messagetypename = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
                BEGIN
                    -- End the conversation
                    END CONVERSATION @ch;
                END

            COMMIT TRANSACTION
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION
            PRINT ERROR_MESSAGE()
        END CATCH
    END
END

此代码用于接收来自InitiatorQueue的响应消息:

代码语言:javascript
复制
ALTER PROCEDURE [dbo].[ProcessMessageWithTimeOut]
    @reference_id UNIQUEIDENTIFIER,
    @receive_timeout INT
AS
BEGIN
    DECLARE @ch UNIQUEIDENTIFIER
    DECLARE @conversation_group_id UNIQUEIDENTIFIER
    DECLARE @messagetypename NVARCHAR(256)
    DECLARE @messagebody XML
    DECLARE @responsemessage XML
    DECLARE @errorcode INT
    DECLARE @errormessage NVARCHAR(3000)
    DECLARE @queuing_order BIGINT
    DECLARE @timeout INT

    SET @conversation_group_id = @reference_id
    SET @timeout = @receive_timeout

    DECLARE @tableMessage TABLE
    (
        queuing_order BIGINT,
        conversation_handle UNIQUEIDENTIFIER,
        message_type_name NVARCHAR(256),
        message_body VARBINARY(MAX)
    )

    BEGIN TRY
        BEGIN TRANSACTION
            WAITFOR(
                RECEIVE
                    queuing_order,
                    conversation_handle,
                    message_type_name,
                    message_body
                FROM InitiatorQueue INTO @tableMessage
                WHERE conversation_group_id = @conversation_group_id
            ), TIMEOUT @timeout;

            DECLARE @count INT
            SET @count = (SELECT COUNT(*) FROM @tableMessage)
            IF (@count = 0)
            BEGIN;
                THROW 50001, 'No message response within 5 seconds.', 1
            END

            IF (@count <>2)
            BEGIN
                DECLARE @timeout2 INT
                SET @timeout2 = ABS(@timeout * 0.5)

                WAITFOR(
                    RECEIVE
                        queuing_order,
                        conversation_handle,
                        message_type_name,
                        message_body
                    FROM InitiatorQueue INTO @tableMessage
                    WHERE conversation_group_id = @conversation_group_id
                ), TIMEOUT 5000
                SET @count = (SELECT COUNT(*) FROM @tableMessage)
                IF (@count <> 2)
                BEGIN;
                    THROW 50002, 'End Dialog without Response Message', 1
                END
            END

            WHILE (@count <> 0)
            BEGIN
            SET @queuing_order = (SELECT TOP 1 queuing_order FROM @tableMessage)
            SET @ch = (SELECT conversation_handle FROM @tableMessage WHERE queuing_order = @queuing_order)
            SET @messagetypename = (SELECT message_type_name FROM @tableMessage WHERE queuing_order = @queuing_order)
            SET @messagebody = CAST((SELECT message_body FROM @tableMessage WHERE queuing_order = @queuing_order) AS XML)

                IF (@messagetypename = 'http://ssb.csharp.at/SSB_Book/c03/ResponseMessage')
                BEGIN
                    -- Store the received response message in a table
                    INSERT INTO ProcessedMessages (ID, MessageBody, ServiceName, ProcessedDateTime)
                    VALUES (NEWID(), @messagebody, 'InitiatorService', GETDATE())
                END

                ELSE IF (@messagetypename = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
                BEGIN
                    -- End the conversation on the initiator's side
                    END CONVERSATION @ch
                END
                DELETE FROM @tableMessage WHERE queuing_order = @queuing_order
                SET @count = (SELECT COUNT(*) FROM @tableMessage)
            END

        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() = 50001
        BEGIN
            ;THROW
        END

        IF ERROR_NUMBER() = 50002
        BEGIN
            ;THROW
        END
        ;THROW
        ROLLBACK TRANSACTION
        PRINT ERROR_MESSAGE()
    END CATCH
END

这是我的C#代码,用于调用存储过程:

代码语言:javascript
复制
public async Task<TestObject> Begin_Conversation_With_Group_Id(Guid ch)
{
    try
    {
        return await Context.Database.SqlQuery<TestObject>(
        "EXEC SendingMessage_Group_Id @ch",
        new SqlParameter("ch", ch))
            .SingleOrDefaultAsync();
    }
    catch (Exception e)
    {
        TestObject exception = new TestObject();
        exception.Data = "Cannot get the data due to: " + " " + e.Message;
        return exception;
    }
}

public async Task<TestObject> Process_Response_Message_With_TimeOut(Guid ch)
{
    var timeout = 5000;
    try
    {
        return await Context.Database.SqlQuery<TestObject>(
            "EXEC ProcessMessageWithTimeOut @ch, @timeout",
            new SqlParameter("ch", ch),
            new SqlParameter("timeout", timeout))
                .SingleOrDefaultAsync();
    }
    catch (SqlException ex)
    {
        TestObject exception = new TestObject();
        exception.Data = "Process is not finish yet due to: " + ex.Message + " " + ex.Number;
        return exception;
    }
}

问题是,当我运行代码时,消息仍然在TargetQueue中,应该由内部激活来接收和处理。

但是,如果只调用1存储过程(SendingMessage_Group_Id),它就可以正常工作了。该消息能够响应到InitiatorQueue而不是停留在TargetQueue中。

据我猜测,是因为事务还没有提交。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-19 07:59:17

这个问题已经解决了。

这个问题之所以发生,是因为我使用了一个导致这种情况发生的框架。框架在启动时包含一个事务,所以我需要做的是禁用框架的事务,然后问题就解决了。

我使用的框架是ASP.NET零

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46784523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档