我在Google或SO上找不到任何与我的问题相符的内容。
在SQL Server中,我有一个标量函数(我们称之为dbo.MySqlStringFunction
)。
这个函数的作用是调用用C#编写的实用程序,该实用程序调用ASP.Net视图并将HTML作为SqlString返回。
SQL Server中的函数定义是:
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS EXTERNAL NAME [Utils.UserDefinedFunctions].[MySqlStringFunction]
简化的C#代码是:
var request = (HttpWebRequest)WebRequest.Create("www.mydomain.com");
using (var response = (HttpWebResponse)request.GetResponse())
using (var stream = response.GetResponseStream())
{
using (var streamReader = new StreamReader(stream, Encoding.UTF8)
{
return new SqlString(streamReader.ReadToEnd());
}
}
当我将C#代码放入控制台应用程序并运行它时,我会完全按照应有的方式获取所有内容。
当我直接在浏览器中访问网址时,它会完全按照原样显示。
当我SELECT MySqlStringFunction()
时,诸如™,§,¤等字符分别显示为2或3个问号。
它似乎介于return new SqlString(..)
和sql函数之间,返回值,表明某些事情变得很糟糕。但是我不知道它会是什么。
答案 0 :(得分:2)
问题似乎是return
的位置。当前代码(在问题中显示)返回3个using
块的中间,其中一个是正在读取的UTF-8流。这可能会使事情变得混乱,因为SQLCLR是来自主SQL Server内存的隔离内存,通常您无法通过流返回。最好先关闭开放流,然后让using
块调用Dispose()
。因此:
using
(即string _TempReturn = String.Empty;
)using
内,将return
替换为:_TempReturn = streamReader.ReadToEnd();
using
结束括号下方,添加:return new SqlString(_TempReturn);
(旧答案,将在不久的将来删除)
问题在于网页和SQL Server之间的编码差异。您正在使用Encoding.UTF8
作为网页(鉴于UTF-8是最常用的互联网编码,这很可能是正确的),但SQL Server(以及一般的.NET和Windows)是UTF-16小恩迪安。这就是为什么你为Code Point 127上面的每个字符获得2或3 ?
的原因:UTF-8是一个多字节编码,每个字符使用1,2或3个字节,而UTF-16总是2字节(好的,补充字符是4字节,但这是由于是一对双字节值)。
您需要先将编码转换为UTF-16 Little Endian,或者将其传回流。并且,UTF-16 Little Endian是.NET中的Unicode
编码,而Big Endian Unicode
是指“UTF-16 Big Endian”。因此,您希望转换为Unicode
编码。
或者,它可能是相反的:网页不是UTF-8,在这种情况下你在StreamReader
中错误地声明了它。如果是这样,那么您需要在StreamReader
构造函数中指定正确的编码。