2011-08-22 70 views
13

读取结果的时候,我的存储过程:无效的转换异常从SqlDataReader的

@UserName nvarchar(64), 

    AS 

    BEGIN 
    SELECT MPU.UserName, SUM(TS.Monday)as Monday //TS.Monday contains float value 
    FROM dbo.MapTask MT JOIN dbo.MapPU MPU 
    ON MPU.ID = MT.MPUID 
    JOIN dbo.TimeSheet TS 
    ON MT.TMSID = TS.ID 
    WHERE MT.StartDate = @StartDate_int and MPU.UserName = @UserName 
    GROUP BY MPU.UserName 
    END 

在我的C#代码

SqlDataReader reader = command.ExecuteReader(); 

     while (reader.Read()) 
     { 
      float monday = (float)reader["Monday"]; // Invalid cast exception 
     } 

有人可以告诉我,我做错了什么?谢谢。

+0

您可以尝试Convert.ToFloat(reader [“Monday”]。ToString()); – Jethro

+0

@Jethro:虽然这是一种非常可怕的方式。当转换失败时,用* 2 *转换替换它(字符串和字符串)通常不是一个好主意。 –

+0

@Jon Skeet,这是有道理的,加上Convert.ToFloat不存在。需要更谨慎。如果Convert.ToFloat确实存在,那么最好这样做。 Convert.ToFloat(读取器[ “星期一”]); ?? – Jethro

回答

30

我的猜测是价值被返回为盒装double而不是float。当你的箱子的类型必须是正好的权利。因此,假如我是对的,它不是decimal或类似的东西,你可以使用:

float monday = (float) (double) reader["Monday"]; 

,它会工作。虽然这很丑陋。如果你使用SqlDataReader.GetFloat它应该是正确的如果它是真正的单精度值,它更清晰(IMO)发生了什么。

在另一方面,你的数据可能实际上是未来从数据库返回的double,在这种情况下,你应该(IMO)使用方法:

float monday = (float) reader.GetDouble(column); 

顺便说一句,你确定float实际上是这里最适合的类型吗?通常decimal更合适...

+14

如果SQL Server中的数据类型是“float”,那么调用SqlDataReader.GetFloat会不幸会引发错误,因为命名约定是完全不兼容的。 SQL“float”实际上是双精度值,因此映射到.NET double。 SQL“真实”是映射到.NET浮点的单精度。 .NET的名称在内部不一致,而不是选择“double”和“single”作为关键字,它将“float”混合在一起,而在SQL中它是“float”和“real”,不涉及双精度或单精度。 – Triynko

11

sql float是一个.NET Double,请参阅msdn。 尝试铸造成双。

+0

你可以尝试使用double来浮动,这就是我所做的。 – TheGateKeeper

+0

这是正确的答案。因为SQL服务器分别使用“float”和“real”来引用double和single-precision值,所以发生强制转换异常。我想这是尝试调用SqlDataReader的常见错误。GetFloat在SQL“float”字段上,因为这样做很有意义,但是,可惜的是,您必须调用SqlDataReader.GetDouble。如果您打算存储单精度值,则返回数据库将类型从“float”更改为“real”。他们应该坚持“float32”,“float64”,“int32”,int64“而不是所有这些”小“”小“”大“”真“”单“”双“废话。 – Triynko

1

我也有过类似的问题,最终做此:

if (!oDR.IsDBNull(0)) 
    Rating = (float)oDR.GetSqlDecimal(0).Value; 

oDR.GetFloat(0)正在恢复和访问SELECT AVG(...)的结果时无效强制转换异常

HTH