SqlParameter的奇怪行为

时间:2018-09-28 15:11:17

标签: .net indexoutofboundsexception sqlclient

使用.Net 4.5.2,我有以下示例代码...

var cmd = new SqlCommand();
cmd.Parameters.Add(new SqlParameter("@CONTENTHYPERLINK", SqlDbType.VarChar, 50));
cmd.Parameters["@contentHyperlink"].Value = "hello world";

第三个链接导致IndexOutOfRangeException异常

但是,如果我使用以下的 any (纯粹改变参数名称的大小写),就可以了!

cmd.Parameters["@CONTENTHYPERLINK"].Value = "hello world";
cmd.Parameters["@contenthyperlink"].Value = "hello world";
cmd.Parameters["@contenTHYperlink"].Value = "hello world";

如果我使用以下任意,则不起作用 ...

cmd.Parameters["@contentHyperlink"].Value = "hello world";
cmd.Parameters["@contentHYPERLINK"].Value = "hello world";
cmd.Parameters["@CONTENtHYPERLINK"].Value = "hello world";

(还有很多可以工作和不工作的示例,我不会在这里列出。)

为什么实际上不区分大小写的某些东西在某些情况下会引发异常?

(我意识到问题的解决方案是使用不会引起异常的解决方案,但我想知道为什么会发生这种情况)


更新

将代码更改为大写后,另一个sproc参数发生了完全相同的事情...

cmd.Parameters["@PortalLastLogon"]  <-- Fails
cmd.Parameters["@portalLastlogon"]  <-- Fails

cmd.Parameters["@PORTALLASTLOGON"]  <-- Works
cmd.Parameters["@portallastlogon"]  <-- Works

这让我发疯了...如果我还有头发要拔出来,我会像现在一样秃顶。

任何人都可以解释到底发生了什么事!!

我有一个带有超过2400个sproc参数的软件...我花时间没有时间全部更新它们!

1 个答案:

答案 0 :(得分:1)

我发现发生这种情况的原因是我们最近引入了用于语言文化处理的代码。

在我的ASP.Net Web应用程序的[Global].Application_BeginRequest部分中,我正在设置以下内容...

var culture = new Globalization.CultureInfo(cultureCode);
Threading.Thread.CurrentThread.CurrentCulture = culture;
Threading.Thread.CurrentThread.CurrentUICulture = culture;

我正在使用的特定语言是威尔士语(代码cy),对于这种文化,在不区分大小写的检查中一定存在一些非常奇怪的现象,这意味着它不匹配。

当我把它放回英语的那一刻,问题就消失了。

目前,我没有关于如何的答案,我将在不将每个sproc调用都更新为大写的情况下解决该问题……但至少我有一个原因为什么失败。


深入研究the .Net source code表明IndexOf既在使用EntityUtil.SrcCompare做直接的==比较...又在使用EntityUtil.DstCompare做文化基于Compare

所以至少我有证据证明这种文化正在发挥作用。


以下内容将演示该问题(使用与EntityUtil.DstCompare相同的CompareOptions)...

using System.Threading;
using System.Globalization;

Thread.CurrentThread.CurrentCulture = new CultureInfo("en");
var enResult = CultureInfo.CurrentCulture.CompareInfo.Compare("lL", "LL",
    CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase);
// enResult == 0 as expected

Thread.CurrentThread.CurrentCulture = new CultureInfo("cy");
var cyResult = System.CurrentCulture.CompareInfo.Compare("lL", "LL",
    CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase);
// cyResult == -1 

由于我需要系统在这种文化下运行,因此我别无选择,只能编写脚本来更新所有Parameters[xxx],以完全符合定义的大小写。