偶然发现了一个简单的错误,它提示了一个有趣的问题。环境: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
由于代码在调试模式下运行并在该行中断,我输入了立即窗口:
?(short) cm.Parameters[0].Value
结果是:
Cannot unbox 'cm.Parameters[0].Value' as a 'short'
好的,SQL sproc返回一个32位的int
(不是我最初认为的16位short
),这解释了异常。应该为此参数使用适当的宽度 - 没有任何问题。
但任何人都可以解释为什么错误的根本原因仅在立即窗口中报告? Exception Helper中没有公开任何细节,内部异常为空。知道确切原因不是有益的吗?我认为它会使错误分析更简单,不是吗?
编辑:添加了屏幕截图;堆栈跟踪似乎没有暗示任何ADO.NET代码(我没想到)。更重要的是,如果我将ret-value参数“声明”保留为SmallInt
,但是提供一个适当宽度的变量(或如图所示),适应int
,一切正常!我非常肯定与ADO / SQL没有任何关系。
我相信@HansPassant揭示了这里发生的事情的真实本质,我倾向于接受这个作为答案。虽然发现托管的代码甚至无法向我提供有关执行状态的准确详细信息(例如,哪个引用实际上为null - 如上所述,或者在此无效转换的情况下),这有点令人失望。
答案 0 :(得分:0)
如果您分析了由ADO.NET生成的SQL,您可能会发现ADO.NET曾尝试将输出参数显式键入为smallint。因此,当SQL Server执行您的请求时,它会尝试将存储过程返回的值(一个int)分配给您告诉它创建为tinyint的变量。我相信您看到的强制转换异常来自SQL Server,而不是.NET。
在命令窗口中,您使用的是CLR,而不是TSQL查询引擎。您的抱怨可能需要使用查询引擎,而不是.NET。