14

这个错误看起来是由在服务器上安装框架 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 === End

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

有谁知道为什么这以前有效而现在无效?

Microsoft 是否进行了任何内部更改以删除隐式转换,或者它以前是否通过纯魔法起作用?

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

=== 更新 3

只是为了完成这个。

我发现了框架之间的变化。在更新中,微软改变了装箱和拆箱的方式。这导致了从 byte 到 int 的隐式转换,当字节被装箱时,旧固件确实失败了,就像它在数据表中一样。

未装箱的字节将在 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

4

5 回答 5

26

它不应该起作用。这使得框架中的某些东西很可能是固定的。

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 的部分内容。

于 2012-10-10T12:37:16.310 回答
6

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

(int)(byte)datarow["tinyintcolumn"];
于 2012-10-10T12:35:38.387 回答
2

因为tinyint是一种Byte类型。这是一个列表:列表

您需要转换byte arrayint. 这里的解决方案:解决方案

于 2012-10-10T12:36:46.197 回答
2

为了使答案可与其他连接库一起使用,我分享了这个。我正在使用 MariaDb 和 MySql 连接器/网络,因此选择的答案对我没有直接作用。所以首先你必须找出返回的 sql tinyint 字段的 C# 数据类型。

这是示例:

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

SELECT tinyintcolumn FROM datatable WHERE ...

我收到“指定的演员表无效!” 即使我在 SQL 查询中使用了强制转换函数,也会出现异常:

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];
于 2015-10-26T09:45:00.220 回答
0

I believe the size of SQL's tinyint is 1 byte (8 bits) so try casting it to a 'byte' instead of casting it to an 'int' (which is 32 bits). But I have not tried this since I don't use tinyint in my database.

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

Also, if your column in the database tinyintcolumn is nullable, you also need to take that into account when you cast the value.

于 2012-10-10T12:43:09.460 回答