SQL Server Service Broker
服务体系结构

消息类型 — 定义应用程序间交换的消息的名称。还可以选择是否验证消息。
约定 — 指定给定会话中的消息方向和消息类型。
队列 — 存储消息。此存储机制使服务间可以进行异步通信。Service Broker 队列还有其他优点,比如自动锁定同一个会话组中的消息。
服务 — 是可寻址的会话端点。Service Broker 消息从一个服务发送到另一个服务。服务指定一个队列来保存消息,还指定一些约定,约定指明该服务可作为“目标”。约定向服务提供一组定义完善的消息类型。

处理的先决条件.

USE master;
GO

ALTER DATABASE 目标数据库
      SET ENABLE_BROKER;
GO

-- 如果上面的操作执行后,长时间无反应,有死机的嫌疑,尝试下面的语句。
ALTER DATABASE 目标数据库 SET NEW_BROKER WITH ROLLBACK IMMEDIATE;

GO
ALTER DATABASE 目标数据库 SET ENABLE_BROKER;

GO

USE 目标数据库;
GO

-------------------- Hello World 的例子 --------------------

-- 创建 SayHelloMessage 消息类型.
-- 该消息类型,不做数据验证的处理.
CREATE MESSAGE TYPE SayHelloMessage
    VALIDATION = None;
GO

-- 创建 约定 SayHelloContract
-- 定义了,发送/接收方.
-- 都是用这个消息类型.
CREATE CONTRACT SayHelloContract (
  SayHelloMessage SENT BY ANY
);
GO

-- 创建发送/接收队列
CREATE QUEUE SayHelloSendQueue;
CREATE QUEUE SayHelloReceiveQueue;
GO

-- 创建发起方服务 SayHelloSendService
-- 该服务使用 SayHelloSendQueue 队列
-- 由于未指定约定名称,因而其他服务不可将此服务用作目标服务。
CREATE SERVICE SayHelloSendService
  ON QUEUE SayHelloSendQueue;
GO

-- 创建目标服务 SayHelloReceiveService
-- 该服务使用 SayHelloReceiveQueue 队列
-- 使用 SayHelloContract 约定
CREATE SERVICE SayHelloReceiveService
  ON QUEUE SayHelloReceiveQueue
    ([SayHelloContract]);
GO

-- 测试发送.
BEGIN
  -- 定义发送的句柄.
  DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

-- 定义变量.
  DECLARE @MyMessage NVARCHAR(100);
  -- 设置发送消息的内容.
  SET @MyMessage = N'Hello World!'

-- 开始事务处理.
  BEGIN TRANSACTION;
  -- 定义消息发送处理.
  BEGIN DIALOG @InitDlgHandle
    FROM SERVICE  -- 定义发送服务.
      SayHelloSendService
    TO SERVICE    -- 定义接收服务.
      N'SayHelloReceiveService'
    ON CONTRACT   -- 定义使用的约定
      SayHelloContract
    WITH  -- 不加密.
      ENCRYPTION = OFF;
  -- 发送消息.
  SEND ON CONVERSATION @InitDlgHandle
    MESSAGE TYPE
      [SayHelloMessage]
        ( @MyMessage );
-- 输出接收到的消息.
PRINT '我发送了:' + @MyMessage;
  -- 提交事务.
  COMMIT TRANSACTION;
END
GO

-- 测试接收,处理,并反馈.
BEGIN
  -- 接收句柄.
  DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
  -- 接收到的数据.
  DECLARE @RecvReqMsg NVARCHAR(100);
  -- 接收到的数据类型名称.
  DECLARE @RecvReqMsgName sysname;
  -- 开始事务处理.
  BEGIN TRANSACTION;
  -- 尝试从 SayHelloReceiveQueue 队列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
      @RecvReqDlgHandle = conversation_handle,
      @RecvReqMsg       = message_body,
      @RecvReqMsgName   = message_type_name
    FROM SayHelloReceiveQueue
  ),  TIMEOUT 1000;

-- 如果接收到的消息类型名为 SayHelloMessage
  -- 那么进行处理.
  IF @RecvReqMsgName = N'SayHelloMessage'
  BEGIN
    -- 定义准备用于返回的消息.
    DECLARE @ReplyMsg NVARCHAR(100);
    -- 简单设置.
    SELECT @ReplyMsg = '~' + @RecvReqMsg + '~';
-- 调试输出.
PRINT '我接收到:' + @RecvReqMsg + "; 我将反馈:" + @ReplyMsg;
    -- 发送反馈消息.
    SEND ON CONVERSATION @RecvReqDlgHandle
      MESSAGE TYPE
        [SayHelloMessage]
          (@ReplyMsg);
    END CONVERSATION @RecvReqDlgHandle;
  END;
  -- 提交事务.
  COMMIT TRANSACTION;
END
GO

-- 测试获取处理结果.
BEGIN
  DECLARE @RecvReplyMsg NVARCHAR(100);
  DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER;
  -- 开始事务处理.
  BEGIN TRANSACTION;
  -- 尝试从 SayHelloReceiveQueue 队列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
    @RecvReplyDlgHandle = conversation_handle,
    @RecvReplyMsg = message_body
    FROM SayHelloSendQueue
  ), TIMEOUT 1000;
  END CONVERSATION @RecvReplyDlgHandle;
-- 输出接收到的消息.
PRINT '我接收到反馈:' + @RecvReplyMsg;
  -- 提交事务.
  COMMIT TRANSACTION;
END
GO

-------------------- Hello World 内部激活的例子 --------------------

-- 专门用于处理消息的存储过程.
CREATE PROCEDURE SayHelloQueueProc
AS
BEGIN
  -- 接收句柄.
  DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
  -- 接收到的数据.
  DECLARE @RecvReqMsg NVARCHAR(100);
  -- 接收到的数据类型名称.
  DECLARE @RecvReqMsgName sysname;
  -- 循环处理.
  WHILE (1=1)
  BEGIN
    -- 开始事务处理.
    BEGIN TRANSACTION;
    -- 尝试从 SayHelloReceiveQueue 队列 接收消息.
    WAITFOR
    ( RECEIVE TOP(1)
        @RecvReqDlgHandle = conversation_handle,
        @RecvReqMsg       = message_body,
        @RecvReqMsgName   = message_type_name
      FROM SayHelloReceiveQueue
    ), TIMEOUT 5000;

-- 判断有没有获取到消息.
    IF (@@ROWCOUNT = 0)
    BEGIN
      -- 如果没有接收到消息
      -- 回滚事务.
      ROLLBACK TRANSACTION;
      -- 跳出循环.
      BREAK;
    END

-- 如果接收到的消息类型名为 SayHelloMessage
    -- 那么进行处理.
    IF @RecvReqMsgName = N'SayHelloMessage'
    BEGIN
      -- 定义准备用于返回的消息.
      DECLARE @ReplyMsg NVARCHAR(100);
      -- 简单设置.
      SELECT @ReplyMsg = '~' + @RecvReqMsg + '~';
-- 调试输出.
PRINT '我接收到:' + @RecvReqMsg + "; 我将反馈:" + @ReplyMsg;

-- 发送反馈消息.
       SEND ON CONVERSATION @RecvReqDlgHandle
         MESSAGE TYPE
           [SayHelloMessage]
              (@ReplyMsg);
       END CONVERSATION @RecvReqDlgHandle;
    END;
    -- 提交事务.
    COMMIT TRANSACTION;
  END
END
GO

-- 更改目标队列以指定内部激活
-- 也就是当有消息发送到 SayHelloReceiveQueue 队列的时候.
-- 自动调用 SayHelloQueueProc 存储过程 进行处理.
ALTER QUEUE SayHelloReceiveQueue
  WITH ACTIVATION
    ( STATUS = ON,
      PROCEDURE_NAME = SayHelloQueueProc,
      MAX_QUEUE_READERS = 10,
      EXECUTE AS SELF
    );
GO

-- 由于消息已经处于自动处理的方式。
-- 测试发送 并 接收.
BEGIN
  -- 定义发送的句柄.
  DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

-- 定义变量.
  DECLARE @MyMessage NVARCHAR(100);
  -- 设置发送消息的内容.
  SET @MyMessage = N'Hello World!'

-- 开始事务处理.
  BEGIN TRANSACTION;
  -- 定义消息发送处理.
  BEGIN DIALOG @InitDlgHandle
    FROM SERVICE  -- 定义发送服务.
      SayHelloSendService
    TO SERVICE    -- 定义接收服务.
      N'SayHelloReceiveService'
    ON CONTRACT   -- 定义使用的约定
      SayHelloContract
    WITH  -- 不加密.
      ENCRYPTION = OFF;
  -- 发送消息.
  SEND ON CONVERSATION @InitDlgHandle
    MESSAGE TYPE
      [SayHelloMessage]
        ( @MyMessage );
-- 输出接收到的消息.
PRINT '我发送了:' + @MyMessage;
  -- 提交事务.
  COMMIT TRANSACTION;

-- 等待 5 秒.
  WAITFOR DELAY '00:00:05';

DECLARE @RecvReplyMsg NVARCHAR(100);
  DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER;
  -- 开始事务处理.
  BEGIN TRANSACTION;
  -- 尝试从 SayHelloReceiveQueue 队列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
    @RecvReplyDlgHandle = conversation_handle,
    @RecvReplyMsg = message_body
    FROM SayHelloSendQueue
  ), TIMEOUT 1000;
  END CONVERSATION @RecvReplyDlgHandle;
-- 输出接收到的消息.
PRINT '我接收到反馈:' + @RecvReplyMsg;
  -- 提交事务.
  COMMIT TRANSACTION;

END
GO

我发送了:Hello World!

(1 行受影响)
我接收到反馈:~Hello World!~

SQL Server Service Broker 简单例子 (转)的更多相关文章

  1. Reusing dialogs with a dialog pool--一个sql server service broker例子

    一个sql server service broker例子 ----------------------------------- USE master GO -------------------- ...

  2. SQL Server Service Broker创建单个数据库会话

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  3. SQL Server Service Broker创建单个数据库会话(消息队列)

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  4. The SQL Server Service Broker for the current database is not enabled

    把一个数据恢复至另一个服务器上,出现了一个异常: The SQL Server Service Broker for the current database is not enabled, and ...

  5. 在Windows Server 2008 R2 Server中,连接其他服务器的数据库遇到“未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker ”

    项目代码和数据库部署在不同的Windows Server 2008 R2 Server中,错误日志显示如下: "未启用当前数据库的 SQL Server Service Broker,因此查 ...

  6. SQL Server Service Broker(简称SSB)资料

    SQL server Service Broker (下面简称SSB) 是SQL server 里面比较独特的一个功能.它可帮助开发人员构建异步的松散耦合应用程序.SSB的一些功能和好处包括有: 数据 ...

  7. sql server Service Broker 相关查询

    sql server Service Broker 相关查询 -- 查看传输队列中的消息 --如果尝试从队列中移除时,列将表明哪里出现了问题 select * from sys.transmissio ...

  8. SQL问题:未启用当前数据库的 SQL Server Service Broker

    数据库分离后,附加回到数据库,然后在程序中打开调用数据库的页面,出现如下问题:“未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持.如果希望使用通知,请为此数 ...

  9. 未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker

    昨晚遇到的这个问题,也知道Notifications service依赖底层的Service broker的.本以为只需要执行以下脚本对数据库启用Service broker即可. alter dat ...

随机推荐

  1. Redis实战(七)

    修改数据 C#语言修改Redis示例. 1.通过key修改单个value using (var redisClient = RedisManager.GetClient()) { var user = ...

  2. linux下安装nodejs及linux下解压tar.xz文件

    1.下载nodejs的安装包  2.解压该文件 在linux下,大部分情况下不能直接解压tar.xz的文件. 需要用xz -d xxx.tar.xz 将 xxx.tar.xz解压成 xxx.tar 然 ...

  3. [hdu3934] 凸包 旋转卡壳

    大致题意: 求多边形的最大内接三角形 旋转卡壳 模板题 #include<cstdio> #include<iostream> #include<cstring> ...

  4. HDU 6186 CS Course

    保存前缀后缀. 保存一下前缀和后缀,去掉第$i$个位置,就是$L[i-1]$和$R[i+1]$进行运算. #include<bits/stdc++.h> using namespace s ...

  5. 洛谷P2657 [SCOI2009]windy数 [数位DP,记忆化搜索]

    题目传送门 windy数 题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个win ...

  6. 如何安装及使用PuTTY

    http://www.ytyzx.net/index.php?title=%E5%A6%82%E4%BD%95%E5%AE%89%E8%A3%85%E5%8F%8A%E4%BD%BF%E7%94%A8 ...

  7. python 写一个贪吃蛇游戏

    #!usr/bin/python #-*- coding:utf-8 -*- import random import curses s = curses.initscr() curses.curs_ ...

  8. socketserver用法列子

    socketserver socketserver内部使用IO多路复用以及“多线程”和“多进程”,从而实现并发处理多个客户端请求的scoket服务端.即,每个客户端请求连接到服务器时,socket服务 ...

  9. 安卓 onTouch OnTouchEvent onChick 顺序

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 分发触摸事件 -> 在 触摸 时候 -> 在触摸事件时候->在点击时候 ...

  10. codevs 1226 倒水问题

    1226 倒水问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold   题目描述 Description 有两个无刻度标志的水壶,分别可装 x 升和 y 升 ( x, ...