记录一次.NET CORE下的异常.
异常信息如下:
System.InvalidCastException: Unable to cast object of type ‘System.Boolean’ to type ‘System.SByte’.
通常发生在EF Core查询数据时使用Mysql ,同时表中含有类型为tinyint(1)列的情况下。
EF Core将tinyint(int) 映射为System.SByte类型(按理说应该映射成System.Byte,实际上就是System.Byte,也不知道为啥处理的时候使用SByte,学艺不精,有知道的大佬请一定告知,谢谢!),当我们从Mysql拿数据时,Mysql会将tinyint(int)转换成Boolean类型返回,EF Core拿到这个数据时,会按照映射关系将其转换成System.SByte,然后就会出现以下异常。
System.InvalidCastException: Unable to cast object of type ‘System.Boolean’ to type ‘System.SByte’.
Mysql 的 tinyint 类型可以设置为有符号,也可设置为无符号,所以映射成System.SByte没有问题。
两个解决方案
(1)修改映射关系,在代码中指定实体类中Boolean类型属性的对应数据库类型为bit(1),这样就会形成一个bit(1)<==>boolean的映射。
映射是数据库类型和.NET类型之间的映射,如果你没有指定实体中属性对应的数据库类型,那么EFCore会根据数据库架构,推断出每个属性对应的数据库类型,然后在这个数据库类型的基础上生成和对应.NET类型的映射,之后EFCore处理数据,就只会参照这个映射关系,不会去管你数据库里实际上存的是什么类型,在EFCore眼里,你的数据库类型就是映射关系里的那个类型,会按照那个类型去找对应的.NET类型,然后转换。
举个例子
[MaxLength(1)]
[Required]
[Column("BoolFlag",TypeName = "bit(1)")]
public bool BoolFlag { get; set; }
在数据库里,我存的是tinyint(1)类型,但是我只要在这里指定了数据库类型,那么EFCore只会根据这个去找对应的.NET类型,bit(1)的对应.NET类型就是Boolean类型,所以接收Mysql传来的数据,就会将它转换成Boolean,先前说过Mysql会将tinyint(int)转换成Boolean类型返回,所以就不存在转换失败的问题。
(2)在MySQL连接字符串中添加参数"TreatTinyAsBoolean=false",这样Mysql在处理tinyint(1)类型数据时,会不做转换直接返回,返回的数据是用一个字节存放的0或1,EF Core将对应数据转换成SByte。
从数据库中将数据拉入内存时的转换应该都是隐式的。
从内存中的原始数据到实体类的对象集合,应该存在一个通过构造函数构造或者类似于强制转换的处理,将内存中原始数据的类型转换成实体类指定的类型。
两种方案选择一种即可。
未系统学过.NET,个人理解,如有错误,请一定告知,学习进步!
本文介绍了在使用EF Core查询MySQL数据库时遇到的`System.InvalidCastException`异常,该异常源于tinyint(1)字段被转换为Boolean再尝试转换为SByte。提供了两种解决方案:一是修改映射关系,指定tinyint(1)对应的数据库类型为bit(1);二是设置MySQL连接字符串中的`TreatTinyAsBoolean=false`,避免数据转换。选择任一方案即可解决问题。
1068

被折叠的 条评论
为什么被折叠?



