为什么"指定的强制转换无效"错误*不*暴露根本原因?

Ast*_*tor 15 c# .net-4.0

只是偶然发现了一个简单的错误,它提示了一个有趣的问题.环境:VS 2010,NET.4,C#.从SQL sproc获取返回值会产生"指定的强制转换无效"异常:

cm.Parameters.Add( "@si", SqlDbType.SmallInt ).Direction=   ParameterDirection.ReturnValue;
..
cm.ExecuteNonQuery( );
short   siRetVal=   (short) cm.Parameters[0].Value;     // exception here
Run Code Online (Sandbox Code Playgroud)

由于代码在调试模式下运行并在该行中断,我输入了立即窗口:

?(short) cm.Parameters[0].Value
Run Code Online (Sandbox Code Playgroud)

结果是:

Cannot unbox 'cm.Parameters[0].Value' as a 'short'
Run Code Online (Sandbox Code Playgroud)

好吧,SQL sproc返回一个32位int(不是short我最初想到的16位),这解释了异常.应该为此参数使用适当的宽度 - 没有问题.

但任何人都可以解释为什么错误的根本原因仅在立即窗口中报告?Exception Helper中没有公开任何细节,内部异常为空.知道确切原因不是有益的吗?我认为它会使错误分析更简单,不是吗?


编辑:添加截图; 堆栈跟踪似乎没有暗示任何ADO.NET代码(我没想到).更重要的是,如果我将ret-value参数"声明"保留为SmallInt,但提供一个适当宽度的变量(或如图所示),适应一个int,一切正常!我很确定这与ADO/SQL没有任何关系.

我相信@HansPassant揭示了这里发生的事情的真实本质,我倾向于接受这个作为答案.尽管发现托管代码甚至无法向我提供有关执行状态的准确详细信息(例如,哪个引用实际上为null - 如上所述,或者在此无效转换的情况下),这有点令人失望.

syn*_*ody 0

如果您分析 ADO.NET 生成的 SQL,您可能会发现 ADO.NET 尝试将输出参数显式键入为smallint。因此,当 SQL Server 执行您的请求时,它会尝试将存储过程返回的值(int)分配给您告诉它创建为tinyint 的变量。我相信您看到的强制转换异常来自 SQL Server,而不是 .NET。

在命令窗口中,您使用的是 CLR,而不是 TSQL 查询引擎。您的抱怨可能需要针对查询引擎,而不是 .NET。

  • **抱怨不是关于 SQL-vs-ADO.NET 或值与变量的错误“宽度”来保存它,而是关于缺乏可用于代码的精确信息**。由于立即窗口确实暴露了根本原因,因此_它可以首先包含在异常中_。在许多情况下,这将极大地帮助找出问题所在,最重要的是找出问题的原因。当然,我们学习诸如不在同一行上使用多个复杂表达式之类的技术 - 从而有助于通过行 # 定位异常 - 以查明弱点。恕我直言,这对于 .NET 来说是一个蹩脚的借口。 (2认同)