如何将nvarchar(非英文)传递给CLR(C#)存储过程?

问题描述:

在Visual Studio中工作,我试图使用FOR XML RAW和C#代码中的SqlXml类型的参数(意图使用XmlReader处理行)将整行传递给CLR存储过程。该行包含nvarchar字段。如何将nvarchar(非英文)传递给CLR(C#)存储过程?

当nvarchar字段包含英语/数字/简单标点符号文本时,一切正常工作,但是当它们中的任何一个包含希伯来语或俄语字符时,这些字符都会变成问号。 (对于仅适用于俄文的文本也是如此,因此不是RTL问题)

从SQL代码中的打印我发现由XML RAW创建的xml保留了非英文字符 - 它们打印得很好。但是,当打印sqlXmlParameter.Value(或将其放在输出字符串中并打印在sql中)时,将打印问号而不是非英文字符。 我试过使用SqlString参数并得到相同的结果 - 参数在SQL中看起来不错,但传递给CLR过程时发生更改。

我也发现T-SQL和C#都使用UTF-16作为默认编码,所以这真的很奇怪。

将参数传递给CLR或将编码信息附加到CLR时,如何保留非英文字符?

编辑:此问题涉及以下内容:How to make SqlContext.Pipe.Send in SQLCLR stored proc work with unicode? 事实证明,解决这个问题的另一个问题也是如此。我不确定为什么,因为这种情况下的C#代码不包含非英文字符,但它确实使用了可能不是英文字符串的字符串格式,所以也许有些编码混合是由于常量字符串格式被保存。只是我的猜测。 因此,如果有人遇到相关问题(尽管我对此有模糊的定义),您可能需要尝试一下。

+0

如何将XML从RDBMS传输到应用程序? – Shnugo

+0

@Shnugo我将C#代码添加为存储过程,并从SQL中调用存储过程。据我所知,VS将C#代码转换为程序集并自动创建了调用该程序集AS EXTERNAL的存储过程。 – MASQ

+0

是的,默认情况下,Windows/.NET/SQL Server('NVARCHAR' /'NCHAR' /'XML')中的字符串是UTF-16 Little Endian。当从SQL Server的XML传输到SQLCLR对象时,无论是“SqlXml”还是“SqlString”/“SqlChars”,都不应该改变字符。你有没有尝试'SqlChars',它给你一个'char []'?你可以从中创建一个新的字符串:'string _Test = new string(SqlCharsParam.Value);'。 –

没有提供任何示例代码(C#或者甚至是调用存储过程的T-SQL),所以很难说明问题,但是您可能在如何调用存储过程时出错。很可能你并没有在Unicode和XML文字前面加上N以使它们保持为Unicode。下面的C#代码和T-SQL显示,SQLCLR不正确接受并在所有三个数据类型显示Unicode字符:SqlStringSqlCharsSqlXml(样品希伯来语和俄语文字从您的相关问题采取):

C#

using System; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 

public class UnicodeTesting 
{ 
    [Microsoft.SqlServer.Server.SqlProcedure] 
    public static void PrintTest(SqlString StringParam, SqlChars CharsParam, 
           SqlXml XmlParam) 
    { 
     SqlContext.Pipe.Send("Unicode test: blip"); 
     SqlContext.Pipe.Send("Unicode test: בליפ"); 
     SqlContext.Pipe.Send("Unicode test: Блип"); 

     SqlContext.Pipe.Send("StringParam: " + StringParam.Value); 
     SqlContext.Pipe.Send("CharsParam: " + new String(CharsParam.Value)); 
     SqlContext.Pipe.Send("XmlParam: " + XmlParam.Value); 
    } 
} 

T-SQL

EXEC dbo.PrintTest N'בליפ a', 
        N'בליפ b', 
        N'<test>בליפ c</test><test>Блип</test>'; 

输出(在“消息”选项卡中)

Unicode test: blip 
Unicode test: בליפ 
Unicode test: Блип 
StringParam: בליפ a 
CharsParam: בליפ b 
XmlParam: <test>בליפ c</test><test>Блип</test> 
+0

我将FOR XML的结果作为存储过程参数传递,参数是XML类型的,所以我不能直接附加N'。当我打印生成的xml进行调试时,非英文显示正常。服务器下来atm,但我可以尝试发送它作为nvarchar,而不是看看是否有帮助(会增加一些转换开销)。 – MASQ

+0

@MASQ你仍然太模糊,我真的帮助。我知道该参数是XML,但您显然首先将FOR XML的结果存储在变量中。您需要使用您用来生成XML的T-SQL更新问题并调用SQLCLR存储过程。 –

+0

呃,我只是在工作上有点新鲜,并不确定政策是关于其他人的代码(或任何)。我打算发布一个编辑过的代码示例,但看起来像改变C#代码上的保存设置(来自您在我另一个问题上的答案)以某种方式解决了这个问题。 – MASQ