这个错误看起来像是在服务器上安装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更新中。这还有待回答:)
答案 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)
答案 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中的列可以为空,则还需要在转换值时将其考虑在内。