为什么函数在作为 SQL 服务器 CLR UDF 执行时会输出不同的结果?

Why would a function output different results when executing as a SQL Server CLR UDF?

我正在使用 .Net DLL 对字符串进行哈希处理,以便稍后比较它们。

我已将对该函数的调用包装在 SQL 服务器 CLR UDF 中并发布在服务器上。

现在,当我执行函数时,输出与 运行 运行控制台应用程序时得到的输出不同。

函数签名如下:

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 CalculateHash(SqlString input)
{
    string unwrappedValue = input.Value.Normalize();
    int hash = HashCalculator.Calculate(unwrappedValue);
    return new SqlInt32(hash);
}

如您所见,我在计算哈希值之前解包并规范化字符串。因此,无论我从何处调用该代码,我都希望结果是相同的。

给定字符串 Test 123 我得到:

-387939562 - When running from a Console Application
137570918  - When calling from SQL Server

SQL 服务器 UDF 不允许 Debug.Print(或类似)调用。

并且出于某种原因,Visual Studio 在调试 UDF 时不会在 *.cs 文件断点处停止(但这是一个不同的问题,我仍在努力解决)。

我的问题是:为什么同一个函数会给出两个不同的结果?可能导致此问题的 UDF 有什么问题?我什至尝试更改数据库中的排序规则,但它不会影响函数的结果。

编辑:我在 运行 查询 sql 时管理了进入代码的步骤,并发现方法 String.GetHashCode() 在 [=52 时返回了不同的值=]宁内 SQL 服务器。无论如何,我假设任何类似字符集的问题都会消失,因为我在使用它之前对字符串进行了规范化。

编辑 2:鉴于 GetHashCode 似乎是问题所在,我在这里检查了它的代码:

How is GetHashCode() of C# string implemented?

并发现 .net 实现不同于 运行ning 32 位 x 64 位。当我在 64 位模式下将控制台设置为 运行 时,输出结果与我在 SQL 服务器中获得的结果相同。

一旦我设法在 SQL 服务器上调试 UDF 运行ning,我终于能够弄清楚我用来散列给定字符串的算法依赖于 .net 的 GetHashCode方法。

并且至少对于 String class,根据 this question,原始实现在 32 位和 64 位平台上给出了不同的结果。

因此,当我在控制台应用程序上 运行ning 测试功能时,它最终 运行ning 作为 32 位应用程序。但是 SQL 服务器安装的是 64 位,迫使 GetHashCode 的其他实现为 运行。

通过强制控制台应用程序 运行 作为 64 位应用程序,我能够复制 SQL 服务器的结果。

然后,只需调整参数即可使 32 位和 64 位平台给出相似(但不相等)的结果。