【问题标题】:Is it possible to use variables with the 'DIALOG' and 'CONVERSATION' commands?是否可以通过“DIALOG”和“CONVERSATION”命令使用变量?
【发布时间】:2020-10-10 05:58:57
【问题描述】:

我已经能够设置我的 Visual Studio (2019) 数据库项目,并为表、存储过程、视图等很好地使用数据库引用。它们似乎都与我导入的架构匹配得很好。但是,在引用同一数据库的合同、类型、服务等时,我似乎无法避免错误。当我引用目标数据库的服务时,我没有问题(我认为这是因为它接受基本的 NVARCHAR 字符串而不是强类型模式。

我有以下示例,它只是将消息发送到另一个数据库的服务。我收到错误消息:“SQL71502:过程:[dbo].[z_Queue_SendMessage] 对对象 [@VariableName] 的引用未解析”,@VariableName 是以下所有内容:(@RequestMessageType、@BasicContract、@InitiatorService)

CREATE PROCEDURE [dbo].[z_Queue_SendMessage]
    @ProcedureName VARCHAR(1000) = 'Procedure', 
    @SubProcedureName VARCHAR(500) = 'SO', 
    @ProcedureType VARCHAR(200) = 'Delete', 
    @Inserted AS XML = NULL, 
    @Deleted AS XML = NULL
AS


DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

DECLARE @RequestMsg NVARCHAR(MAX);
DECLARE @Message XML;

DECLARE @RequestMessageType NVARCHAR(100) = '//$(WebDb)' + N'/Queue/RequestMessage'
DECLARE @InitiatorService NVARCHAR(100) = '//$(WebDb)' + N'/Queue/InitiatorService'
DECLARE @BasicContract NVARCHAR(100) = '//$(WebDb)' + N'/Queue/BasicContract'
DECLARE @TargetService NVARCHAR(100) = '//$(WebDb)' + N'/Queue/TargetService'


BEGIN TRANSACTION;

BEGIN DIALOG @InitDlgHandle
        FROM SERVICE [@InitiatorService] --Here
        TO SERVICE @TargetService
        ON CONTRACT [@BasicContract] --Here
        WITH
            ENCRYPTION = OFF;

SET @Message = (SELECT
                ProcedureName    = @ProcedureName,
                SubProcedureName = @SubProcedureName,
                ProcedureType    = @ProcedureType,
                Inserted         = @Inserted,
                Deleted          = @Deleted
            FOR XML PATH('Request'));

SEND ON CONVERSATION @InitDlgHandle
        MESSAGE TYPE [@RequestMessageType] --Here
        (@Message);

SELECT @Message AS SentRequestMsg;

COMMIT TRANSACTION;

有没有什么方法可以格式化它,这样我就不会在不使用动态 SQL 的情况下收到错误消息?如果我无法通过抑制错误或使用动态 SQL 来确认它与数据库模式匹配,那么它就达不到目的。

【问题讨论】:

  • [@variable] 在任何命令中的这种用法中都不会有效,因为它引用了一个名为“@variable”的标识符[..] 构造引用任何内容,例如select 1 as [I am a column, @novariableshere!](与select 1 as "I am a column, @novariableshere!" 相同)。
  • 它适用于创建合同。这在没有错误/警告的情况下完成,并且在部署到数据库时似乎工作正常。虽然,它是一个脚本而不是 SP。创建合同 [@BasicContract] ([@RequestMessageType] SENT BY INITIATOR, [@ReplyMessageType] SENT BY TARGET );去
  • 我会检查数据库中的合同名称..
  • 合约名称看起来不错。有没有可能它不是用 DACPAC 文件提取的?我希望以这种方式引用它们,而不是将其构建到数据库项目中,但这可能是我唯一的选择,可以在没有警告的情况下编译它,假设它有效。
  • @NathanChampion,您确定合同名称与变量名称规范一致吗?我希望合同被命名为变量名,而不是变量的值:SELECT * FROM sys.service_contracts WHERE name = '@BasicContract';

标签: sql-server schema database-project


【解决方案1】:

我最终不得不将创建脚本/文件导入到我的 Visual Studio 数据库项目中,以使这一切正常工作而不会出现语法错误。

我尝试在未选中“仅包含应用程序范围的对象”和选中“包含扩展属性”的情况下提取 DACPAC,但仍然遇到与之前相同的问题。

我在我的项目中为消息、服务和合同添加了单独的 SQL 项。例子:

服务:

CREATE SERVICE [//Web/Queue/InitiatorService]
    ON QUEUE DataQueue;

合同:

CREATE CONTRACT [//Web/Queue/BasicContract]
(
    [//Web/Queue/RequestMessage] SENT BY INITIATOR,
    [//Web/Queue/ReplyMessage] SENT BY TARGET
)

消息类型:

CREATE MESSAGE TYPE [//Web/Queue/ReplyMessage]
       VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE [//Web/Queue/RequestMessage]
    VALIDATION = WELL_FORMED_XML;

这使我仍然能够符合数据库架构并避免将来出现错误。我 确实 仍然使用 SQLCMD 变量引用目标服务,因此除了开发环境和生产环境中的服务外,我可以使用相同的名称。这是我现在发送消息的存储过程:

CREATE PROCEDURE [dbo].[z_Queue_SendMessage]
    @ProcedureName VARCHAR(1000) = 'Procedure', 
    @SubProcedureName VARCHAR(500) = 'SO', 
    @ProcedureType VARCHAR(200) = 'Delete', 
    @Inserted AS XML = NULL, 
    @Deleted AS XML = NULL
AS


DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

DECLARE @RequestMsg NVARCHAR(MAX);
DECLARE @Message XML;

DECLARE @TargetService NVARCHAR(100) = N'//$(WebDb)/Queue/TargetService'

BEGIN TRANSACTION;

BEGIN DIALOG @InitDlgHandle
        FROM SERVICE [//Web/Queue/InitiatorService]
        TO SERVICE @TargetService
        ON CONTRACT [//Web/Queue/BasicContract]
        WITH
            ENCRYPTION = OFF;

SET @Message = (SELECT
                ProcedureName    = @ProcedureName,
                SubProcedureName = @SubProcedureName,
                ProcedureType    = @ProcedureType,
                Inserted         = @Inserted,
                Deleted          = @Deleted
            FOR XML PATH('Request'));

SEND ON CONVERSATION @InitDlgHandle
        MESSAGE TYPE [//Web/Queue/RequestMessage]
        (@Message);

SELECT @Message AS SentRequestMsg;

COMMIT TRANSACTION;

【讨论】:

    【解决方案2】:

    This 有效

    BEGIN DIALOG CONVERSATION @Handle
    FROM        SERVICE @SvcName
    TO          SERVICE @TargetSvc, 'CURRENT DATABASE'
    WITH        ENCRYPTION = OFF
    

    尝试同时引用@InitiatorService@BasicContract@RequestMessageType——这毫无意义。

    【讨论】:

    • 谢谢,这确实解决了编译问题,但不是来自 VS 的参考警告。我要么无法引用服务/合同/类型,要么 DACPAC 根本不包含它。我尝试过使用提取数据库模式的选项,但仍然无法让 VS 将其视为有效参考。我想我可能不得不使用数据库项目本身来部署这些。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2016-10-27
    相关资源
    最近更新 更多