BEGIN DIALOG CONVERSATION (Transact-SQL)

适用于:SQL ServerAzure SQL 托管实例

启动从一个服务到另一个服务的对话。 所谓对话,就是让两个服务能够进行一次顺序消息传递。

Transact-SQL 语法约定

语法

BEGIN DIALOG [ CONVERSATION ] @dialog_handle  
   FROM SERVICE initiator_service_name  
   TO SERVICE 'target_service_name'  
       [ , { 'service_broker_guid' | 'CURRENT DATABASE' }]   
   [ ON CONTRACT contract_name ]  
   [ WITH  
   [  { RELATED_CONVERSATION = related_conversation_handle   
      | RELATED_CONVERSATION_GROUP = related_conversation_group_id } ]   
   [ [ , ] LIFETIME = dialog_lifetime ]   
   [ [ , ] ENCRYPTION = { ON | OFF }  ] ]  
[ ; ]  

注意

若要查看 SQL Server 2014 (12.x) 及更早版本的 Transact-SQL 语法,请参阅早期版本文档

参数

@dialog_handle
一个变量,用于为 BEGIN DIALOG CONVERSATION 语句返回的新对话存储系统生成的对话句柄。 该变量的类型必须为 uniqueidentifier

FROM SERVICE initiator_service_name
指定启动对话的服务。 指定的名称必须是当前数据库中的服务的名称。 为发起方服务指定的队列将接收由目标服务返回的消息,以及 Service Broker 为此会话创建的消息。

TO SERVICE 'target_service_name'
指定启动对话时的目标服务。 target_service_name 的类型为 nvarchar(256)。 Service Broker 会逐字节进行比较以便与 target_service_name 字符串匹配。 换言之,比较时将区分大小写,且不考虑当前的排序规则。

service_broker_guid
指定承载目标服务的数据库。 如果有多个数据库承载目标服务实例,则可通过提供 service_broker_guid 与特定数据库通信。

service_broker_guid 的类型为 nvarchar(128)。 若要查找数据库的 service_broker_guid,请在数据库中运行以下查询:

SELECT service_broker_guid  
FROM sys.databases  
WHERE database_id = DB_ID() ;  

注意

此选项在包含数据库中不可用。

'CURRENT DATABASE'
指定会话使用当前数据库的 service_broker_guid

ON CONTRACT contract_name
指定此会话遵循的约定。 当前数据库中必须有该约定。 如果目标服务不接受遵循指定约定的新会话,Service Broker 将返回针对该会话的错误消息。 如果省略此子句,则会话会遵循名为 DEFAULT 的约定。

RELATED_CONVERSATION =related_conversation_handle
指定将新对话添加到的现有会话组。 如果使用该子句,则新对话与 related_conversation_handle 指定的对话属于同一个会话组。 related_conversation_handle 的类型必须可隐式转换为类型 uniqueidentifier。 如果 related_conversation_handle 不引用现有的对话,则该语句将失败。

RELATED_CONVERSATION_GROUP =related_conversation_group_id
指定将新对话添加到的现有会话组。 如果使用该子句,则新对话将添加到 related_conversation_group_id 指定的会话组中。 related_conversation_group_id 的类型必须可隐式转换为类型 uniqueidentifier。 如果 related_conversation_group_id 不引用现有的会话组,Service Broker 会使用指定的 related_conversation_group_id 创建一个新的会话组,并将新对话与该会话组关联。

LIFETIME =dialog_lifetime
指定对话将保持打开状态的最长时间。 为使对话成功完成,两个端点都必须在生存期内显式结束对话。 dialog_lifetime 的值必须以秒表示。 生存期的类型为 int。如果未指定 LIFETIME 子句,则对话的生存期为 int 数据类型的最大值。

ENCRYPTION
指定在将此对话发送和接收的消息发送到 Microsoft SQL Server 实例外部时是否必须进行加密。 必须加密的对话是安全对话。 如果 ENCRYPTION = ON,但未配置支持加密所需的证书,Service Broker 将返回针对该会话的错误消息。 ENCRYPTION = OFF 时,如果为 target_service_name 配置了远程服务绑定,则使用加密;否则,发送消息时不加密。 如果未使用此子句,则默认值为 ON。

备注

在任何情况下,都不对同一个 SQL Server 实例的服务间交换的消息加密。 但是,如果用于会话的服务位于不同的数据库,则使用加密的会话仍然需要数据库主密钥和加密证书。 这样,在会话进行的过程中,如果将一个数据库移到其他实例,会话仍可继续进行。

注解

所有消息都是会话的一部分。 因此,发起方服务必须在发送消息到目标服务之前启动与目标服务的会话。 BEGIN DIALOG CONVERSATION 语句中指定的信息类似于信函上的地址;Service Broker 使用此信息将消息传递到正确的服务。 TO SERVICE 子句中指定的服务是消息发送到的地址。 FROM SERVICE 子句中指定的服务是用于答复消息的返回地址。

会话目标不需要调用 BEGIN DIALOG CONVERSATION。 当会话中来自发起方的第一条消息到达时,Service Broker 将在目标数据库中创建一个会话。

启动一个对话将在发起服务的数据库中创建一个会话端点,但不创建与承载目标服务的实例的网络连接。 在发送第一条消息之前,Service Broker 不会建立与对话目标的通信。

如果 BEGIN DIALOG CONVERSATION 语句未指定相关的会话或相关的会话组,Service Broker 将为新的会话创建一个新的会话组。

Service Broker 不允许将会话任意分组。 会话组中的所有会话都必须有 FROM 子句中指定的服务作为会话的发起方或目标。

BEGIN DIALOG CONVERSATION 命令将锁定包含返回的 dialog_handle 的会话组。 如果该命令包含 RELATED_CONVERSATION_GROUP 子句,则 dialog_handle 的会话组为 related_conversation_group_id 参数中指定的会话组。 如果该命令包含 RELATED_CONVERSATION 子句,则 dialog_handle 的会话组为与指定的 related_conversation_handle 关联的会话组。

BEGIN DIALOG CONVERSATION 在用户定义函数中无效。

权限

若要启动对话,则当前的用户对于在该命令的 FROM 子句中指定的服务的队列必须有 RECEIVE 权限,对于指定的约定有 REFERENCES 权限。

示例

A. 启动对话

以下实例会启动一个对话会话,并将对话的标识符存储于 @dialog_handle.//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission

DECLARE @dialog_handle UNIQUEIDENTIFIER ;  
  
BEGIN DIALOG CONVERSATION @dialog_handle  
   FROM SERVICE [//Adventure-Works.com/ExpenseClient]  
   TO SERVICE '//Adventure-Works.com/Expenses'  
   ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission] ;  

B. 启动具有显式生存期的对话

以下实例将启动一个对话会话,并将对话的标识符存储于 @dialog_handle//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。 如果 END CONVERSATION 命令在 60 秒内未关闭此对话,则 Broker 将结束此对话并返回错误。

DECLARE @dialog_handle UNIQUEIDENTIFIER ;  
  
BEGIN DIALOG CONVERSATION @dialog_handle  
   FROM SERVICE [//Adventure-Works.com/ExpenseClient]  
   TO SERVICE '//Adventure-Works.com/Expenses'  
   ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission]  
   WITH LIFETIME = 60 ;  

C. 启动具有特定 Broker 实例的对话

以下实例将启动一个对话会话,并将对话的标识符存储于 @dialog_handle//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。 Broker 将此对话的消息路由到由 GUID a326e034-d4cf-4e8b-8d98-4d7e1926c904. 标识的 Broker。

DECLARE @dialog_handle UNIQUEIDENTIFIER ;  
  
BEGIN DIALOG CONVERSATION @dialog_handle  
   FROM SERVICE [//Adventure-Works.com/ExpenseClient]  
   TO SERVICE '//Adventure-Works.com/Expenses',   
              'a326e034-d4cf-4e8b-8d98-4d7e1926c904'  
   ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission] ;  

D. 启动一个对话,并将其关联到现有的会话组

以下实例将启动一个对话会话,并将对话的标识符存储于 @dialog_handle//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。 Broker 将此对话与由 @conversation_group_id 标识的会话组关联,而不创建新的会话组。

DECLARE @dialog_handle UNIQUEIDENTIFIER;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;

SET @conversation_group_id = <retrieve conversation group ID from database>;

BEGIN DIALOG CONVERSATION @dialog_handle
    FROM SERVICE [//Adventure-Works.com/ExpenseClient]
    TO SERVICE '//Adventure-Works.com/Expenses'
    ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission]
    WITH RELATED_CONVERSATION_GROUP = @conversation_group_id;

E. 启动一个具有显式生存期的对话,并将其关联到现有会话

以下实例将启动一个对话会话,并将对话的标识符存储于 @dialog_handle//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。 新对话与 @existing_conversation_handle 属于同一个会话组。 如果 END CONVERSATION 命令在 600 秒内未关闭此对话,Service Broker 将结束此对话并返回错误。

DECLARE @dialog_handle UNIQUEIDENTIFIER;
DECLARE @existing_conversation_handle UNIQUEIDENTIFIER;

SET @existing_conversation_handle = <retrieve conversation handle from database>;

BEGIN DIALOG CONVERSATION @dialog_handle
   FROM SERVICE [//Adventure-Works.com/ExpenseClient]
   TO SERVICE '//Adventure-Works.com/Expenses'
   ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission]
   WITH RELATED_CONVERSATION = @existing_conversation_handle
   LIFETIME = 600;

F. 启动具有可选加密的对话

以下实例将启动一个对话,并将对话的标识符存储于 @dialog_handle//Adventure-Works.com/ExpenseClient 服务是对话的发起方,//Adventure-Works.com/Expenses 服务是对话的目标。 对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。 如果加密不可用,则此示例中的会话允许消息在不加密的状态下通过网络传输。

DECLARE @dialog_handle UNIQUEIDENTIFIER  
  
BEGIN DIALOG CONVERSATION @dialog_handle  
   FROM SERVICE [//Adventure-Works.com/ExpenseClient]  
   TO SERVICE '//Adventure-Works.com/Expenses'  
   ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission]  
   WITH ENCRYPTION = OFF ;  

另请参阅

BEGIN CONVERSATION TIMER (Transact-SQL)
END CONVERSATION (Transact-SQL)
MOVE CONVERSATION (Transact-SQL)
sys.conversation_endpoints (Transact-SQL)