记录一次很少见的Sql异常排查,异常内容:
传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。参数 5 ("@TestValue"): 提供的值不是数据类型 float 的有效实例。请检查源数据中的无效值。例如,小数位数大于精度的数值类型的数据即为无效值。
详细的异常信息如下:
System.Data.SqlClient.SqlException (0x80131904): 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。参数 5 ("@TestValue"): 提供的值不是数据类型 float 的有效实例。请检查源数据中的无效值。例如,小数位数大于精度的数值类型的数据即为无效值。 at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
乍一看异常信息提示的很明显,@TestValue参数的值不是有效的float类型。
但是前端调用接口时,传参也指定了有效的数值,困惑~
{ testValue: 10 }
经过一顿源码分析,发现原来是由于一些业务逻辑的计算(由于脏数据导致了除0行为),最终导致了@TestValue参数的值变成了NAN,从而导致了上述异常的发生。
顺便来个小测试:
Console.WriteLine($"0/0.0d = {0 / 0.0d}"); // 输出:0/0.0d = NaN Console.WriteLine($"0/0.0f = {0 / 0.0f}"); // 输出:0/0.0f = NaN int nZero = 0; //此处需要将除数0声明为变量nZero传入表达式,否则编译不通过 Console.WriteLine($"0/0 = {0 / nZero}"); //引发异常:System.DivideByZeroException:“尝试除以零。” decimal dZero = 0.0m; //此处需要将除数0.0m声明为变量dZero传入表达式,否则编译不通过 Console.WriteLine($"0/0.0m = {0 / dZero}"); //引发异常:System.DivideByZeroException:“尝试除以零。”
有没有发现猫腻?
- 0除以浮点类型(float和double)的0 返回的是NAN
- 0除以十进制类型decimal的0会抛出System.DivideByZeroException异常
- 0除以整型(有符号和无符号)的0会抛出System.DivideByZeroException异常