使用c#创建实例名称包含特殊字符的链接服务器

本文关键字:特殊字符 链接 服务器 包含 创建 实例 使用 | 更新日期: 2023-09-27 17:59:57

我有一个创建新链接服务器的存储过程。

问题是我的InstanceName是"my pc"(包含"-"),因此LinkedServer没有正确生成。我的猜测是,我从c#代码中传递参数的方式有问题,但我找不到解决方案。

我的程序是:

CREATE PROCEDURE 
    [test].[createlinkedserver] 
    (
         @InstanceName  AS SYSNAME
    )
AS
BEGIN
    EXECUTE sys.sp_addlinkedserver
        @server     = N'Server' ,
        @srvproduct = N'' ,
        @provider   = N'SQLNCLI' ,
        @datasrc    = [@InstanceName] ,
        @location   = NULL ,
        @provstr    = NULL ,
        @catalog    = NULL

    EXECUTE master.dbo.sp_serveroption
        @server     = N'Server' ,
        @optname    = N'rpc out' ,
        @optvalue   = N'true'

    EXECUTE master.dbo.sp_serveroption
        @server     = N'Server' ,
        @optname    = N'remote proc transaction promotion' ,
        @optvalue   = N'true'

END

我从c#调用存储过程:

    DbCommand Command = CovertixDB.Database.GetStoredProcCommand("test.createlinkedserver");
    CovertixDB.Database.AddInParameter(Command, "InstanceName", DbType.String,  instanceName);
    CovertixDB.Database.ExecuteNonQuery(Command);

使用c#创建实例名称包含特殊字符的链接服务器

这行不通!@datasrc=[@InstanceName]保留为其他参数:

@datasrc = @InstanceName

相反,更改您的C#代码,如下所示:

DbCommand Command = CovertixDB.Database.GetStoredProcCommand("test.createlinkedserver");
CovertixDB.Database.AddInParameter(Command, "InstanceName", DbType.String,  "[" + instanceName + "]");
CovertixDB.Database.ExecuteNonQuery(Command);

您需要确切地知道从c#应用程序传递给SQL的内容。要进一步尝试将转义移到SQL中,请尝试以下操作:

DECLARE @EscapedInstanceName nvarchar(128)
SET @EscapedInstanceName = '[' + @InstanceName + ']'
EXECUTE sys.sp_addlinkedserver
    @server     = @EscapedInstanceName ,
    @srvproduct = N'' ,
    @provider   = N'SQLNCLI' ,
    @datasrc    = @EscapedInstanceName ,
    @location   = NULL ,
    @provstr    = NULL ,
    @catalog    = NULL

然后查看生成的服务器名称。这将告诉您哪些字符串将进入DataSource。

我将c#更改为:

  DbCommand Command = CovertixDB.Database.GetStoredProcCommand("test.createlinkedserver");
    CovertixDB.Database.AddInParameter(Command, "InstanceName", DbType.AnsiString,  instanceName);
    CovertixDB.Database.ExecuteNonQuery(Command);

我将第2行从DbType.String更改为DbType.AnsiString.

然后就成功了。

事实上,我真的不明白为什么,因为c#DbType.String适合NCHAR,NVARCHAR,而DbType.AnsiString适合CHAR、VARCHAR。

我希望它能与DbType.String…一起工作

有人对此有什么解释吗?