将tiny int转换为int时出错

时间:2012-10-10 12:31:17

标签: c# sql-server casting

这个错误看起来像是在服务器上安装framework 4.5引起的,即使该项目仍然是针对4.0。

4.5替换了CLR,看起来在将tinyint类型的对象拆箱到int时发生了变化。这在4.0中有效,但在安装4.5之后没有。

============================================

请在回答之前阅读整个问题,目前大部分答案都没有回答我提出的问题。

我们今天在使用

从sql中的tinyint转换为int时出错
Daterow datarow = GetOneDatarow(connection,
                         "SELECT tinyintcolumn FROM table1 WHERE id = 4");
int i = (int)datarow["tinyintcolumn"];

这是旧代码已经在产品中存在了几年而没有任何更改,它一直在工作到昨天。 (而且它不是确切的代码,只是足以显示上下文)

===更新

确切的错误消息是:“指定的强制转换无效!”和最后一行

int i = (int)datarow["tinyintcolumn"];

是我们的代码中输出错误的确切行,只更改了变量名和列名。

数据库列是tinyint,默认值为0,没有索引或其他约束。

===结束更新

===更新2

Henk Holterman在他的回复中告诉我,即使是专门为4.0编译的项目,FW 4.5也取代了4.0的CLR,这可以远程改变现有的4.0行为。

我会保持开放一段时间,但到目前为止,他的回答是最有希望的:D ===结束

几个星期前我们从框架3.5改为4.0但是昨天下午重新编译后才发生这种情况,昨天早上相同的代码(即使重新编译后)也像发条一样工作。

有没有人知道为什么之前有效并且现在不能正常工作?

微软是否进行了任何隐藏式转换,或之前是纯粹的魔法使用?

我们通过将数据库列更改为int来解决它,但我仍然对可能导致它现在失败的原因感到好奇。

===更新3

只是为了完成这个。

我发现了框架之间的变化。在更新中,Microsoft更改了装箱和拆箱的方式。这导致从字节到int的隐式转换,当字节被装箱时,旧的FW会失败,因为它在数据表中。

4.5中的未装箱字节将隐式转换为int,但是装箱字节是不能隐式转换的通用对象。

不是,这在3.5 SP1中已更改,因此我们的FW 4.0也应该失败,除非SP1的更新不在4.0更新中。这还有待回答:)

以下是来自MS的票;) https://connect.microsoft.com/VisualStudio/feedback/details/766887/casting-tinyint-from-sql-datarow-to-int-no-longer-possible

5 个答案:

答案 0 :(得分:20)

它应该永远不会奏效。这使得框架中的某些内容得以修复。

C#中的问题:

byte b = 3;       // TinyInt is a Byte
object o = b;     // DataRow[i] is an object
int i = (int)o;   // invalid cast

修复:

int i = (byte)datarow["tinyintcolumn"];

从下面的评论小道:

  

我们已经安装了它,但是这个项目没有编译成4.5,只有4.0,......可能就是这样吗?

  

是的,框架4.5取代了4.0的部分。

答案 1 :(得分:5)

TinyInt类型默认返回一个字节类型,它本身可以转换为int,但db的TinyInt类型不是,所以试试这个:

(int)(byte)datarow["tinyintcolumn"];

答案 2 :(得分:2)

因为tinyintByte类型。这是一个列表:LIST

您需要将byte array转换为int。解决方案:SOLUTION

答案 3 :(得分:1)

为了使答案可用于其他连接库,我分享了这个。我使用MariaDb和MySql connector / Net,所以选择的答案对我来说不起作用。首先,您必须找到返回的sql tinyint字段的C#数据类型。

以下是示例:

我使用MySqlHelper.ExecuteDataset()并执行查询来获取tinyint(4)列:

SELECT tinyintcolumn FROM datatable WHERE ...

我得到了"指定的演员阵容无效!"异常,即使我在SQL查询中使用了cast函数:

SELECT CAST(tinyintcolumn AS int) ...

我是第一次尝试所有在这里和其他地方建议的,但最后有效的是找出c#中的字段类型:

DataTable datatable MySqlHelper.ExecuteDataset(connString, sql).Tables[0];
DataRow datarow = datatable .Rows[0];
Type datatype = datarow.ItemArray[0].GetType();

结果: System.SByte !所以对我来说,使用其中一个很好:

SByte sbTinyint = datarow.Field<SByte>(0);
SByte sbTinyint2 = (SByte)datarow.ItemArray[0];
int iTinyint = (int)datarow.Field<SByte>(0);
int iTinyint2 = (int)(SByte)datarow.ItemArray[0];

答案 4 :(得分:0)

我相信SQL的tinyint的大小是1字节(8位),所以尝试将其转换为'byte'而不是将其转换为'int'(32位)。但我没有尝试过这个,因为我没有在我的数据库中使用tinyint。

byte i = (byte)datarow["tinyintcolumn"];

此外,如果数据库tinyintcolumn中的列可以为空,则还需要在转换值时将其考虑在内。