我正在使用 .Net DLL 来散列字符串,以便稍后我可以比较它们。
我已将对该函数的调用包装在 SQL Server 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 Server UDF 不允许Debug.Print(或类似的)调用。
并且出于某种原因,Visual Studio 在调试 UDF 时不会在 *.cs 文件断点处停止(但这是我仍在尝试解决的另一个问题)。
我的问题是:为什么同一个函数会给出两个不同的结果?可能导致此问题的 UDF 有什么问题?我什至尝试更改数据库中的排序规则,但这不会影响函数的结果。
编辑:我在运行 sql 查询时管理了进入代码的步骤,发现方法 String.GetHashCode() 在 SQL Server 中运行时返回不同的值。无论如何,我假设任何类似字符集的问题都会消失,因为我在使用它之前对字符串进行了规范化。
编辑 2:鉴于 GetHashCode 似乎是问题所在,我在这里检查了它的代码:
How is GetHashCode() of C# string implemented?
并发现 .net 实现不同于运行 32 位 x 64 位。当我让我的控制台以 64 位模式运行时,输出结果与我在 SQL Server 中得到的结果相同。
最佳答案
一旦我设法调试了在 SQL Server 上运行的 UDF,我终于能够弄清楚我用来散列给定字符串的算法依赖于 .net 的 GetHashCode 方法。
至少对于 String 类,根据 this question , 原始实现在 32 位和 64 位平台上给出了不同的结果。
因此,当我在控制台应用程序上运行以测试功能时,它最终作为 32 位应用程序运行。但是安装的 SQL Server 是 64 位的,强制运行 GetHashCode 的其他实现。
通过强制控制台应用程序作为 64 位应用程序运行,我能够复制 SQL Server 的结果。
然后,只需调整参数即可使 32 位和 64 位平台给出相似(但不相等)的结果。
关于.net - 为什么函数在作为 SQL Server CLR UDF 执行时会输出不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40049790/