如何将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#代码不包含非英文字符,但它确实使用了可能不是英文字符串的字符串格式,所以也许有些编码混合是由于常量字符串格式被保存。只是我的猜测。 因此,如果有人遇到相关问题(尽管我对此有模糊的定义),您可能需要尝试一下。
没有提供任何示例代码(C#或者甚至是调用存储过程的T-SQL),所以很难说明问题,但是您可能在如何调用存储过程时出错。很可能你并没有在Unicode和XML文字前面加上N
以使它们保持为Unicode。下面的C#代码和T-SQL显示,SQLCLR不正确接受并在所有三个数据类型显示Unicode字符:SqlString
,SqlChars
和SqlXml
(样品希伯来语和俄语文字从您的相关问题采取):
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>
我将FOR XML的结果作为存储过程参数传递,参数是XML类型的,所以我不能直接附加N'。当我打印生成的xml进行调试时,非英文显示正常。服务器下来atm,但我可以尝试发送它作为nvarchar,而不是看看是否有帮助(会增加一些转换开销)。 – MASQ
@MASQ你仍然太模糊,我真的帮助。我知道该参数是XML,但您显然首先将FOR XML的结果存储在变量中。您需要使用您用来生成XML的T-SQL更新问题并调用SQLCLR存储过程。 –
呃,我只是在工作上有点新鲜,并不确定政策是关于其他人的代码(或任何)。我打算发布一个编辑过的代码示例,但看起来像改变C#代码上的保存设置(来自您在我另一个问题上的答案)以某种方式解决了这个问题。 – MASQ
如何将XML从RDBMS传输到应用程序? – Shnugo
@Shnugo我将C#代码添加为存储过程,并从SQL中调用存储过程。据我所知,VS将C#代码转换为程序集并自动创建了调用该程序集AS EXTERNAL的存储过程。 – MASQ
是的,默认情况下,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);'。 –