.NET+MySQL+NPoco下Lesson类IConvertible转换运行时错误求助
问题
使用.NET搭配MySQL与NPoco框架开发,已为Lesson类实现IConvertible接口,且包含无参构造函数与拷贝构造函数。通过.Query方法可成功读取其他表的数据,但读取Lesson表时,在LastDate字段处触发**「Object must implement IConvertible」**运行时错误,即使使用完整SQL查询也会出现该错误。MySQL中FirstDate与LastDate均为Date类型,FromDate字段无此问题。
数据库连接代码
_connectionString = "Server = 127.0.0.1; Database=test; user id=root; password=root;"; _connection = new MySqlConnection(_connectionString); _connection.Open();
Lesson类代码
[TableName("lessons")] [PrimaryKey("id")] public class Lesson : IConvertible { [Column("id")] public int? LessonId { get; set; } [Column("first_date")] public DateTime FirstDate { get; set; } [Column("last_date")] public DateTime LastDate { get; set; } // ERROR here public Lesson() { Console.WriteLine("Constructor Lesson"); } public Lesson(Lesson torahLesson) { LessonId = Lesson.LessonId; FirstDate = Lesson.FirstDate; LastDate = Lesson.LastDate; } static T ThrowNotSupported<T>() { var ex = ThrowNotSupported(typeof(T)); return (T)ex; } static object ThrowNotSupported(Type type) { throw new InvalidCastException($"Converting type \"{typeof(Lesson)} \" to type \"{type}\" is not supported."); } TypeCode IConvertible.GetTypeCode() { return TypeCode.Object; } // 省略其他IConvertible接口方法实现 DateTime IConvertible.ToDateTime(IFormatProvider provider) => ThrowNotSupported<DateTime>(); // 省略其他接口方法 }
完整错误栈
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at NPoco.MappingHelper.<>c__DisplayClass2_0.b__6(Object src) at NPoco.RowMappers.PropertyMapper.MapValue(GroupResult`1 posName, Object[] values, Func`2 converter, Object instance, PocoColumn pocoColumn, Object defaultValue) at NPoco.RowMappers.PropertyMapper.<>c__DisplayClass8_2.b__3(DbDataReader reader, Object[] values, Object instance) at NPoco.RowMappers.PropertyMapper.<>c__DisplayClass7_0.b__1(DbDataReader reader, Object[] values, Object instance) at NPoco.RowMappers.PropertyMapper.Map(DbDataReader dataReader, RowMapperContext context) at NPoco.MappingFactory.Map(DbDataReader dataReader, Object instance) at NPoco.Database.Read[T](Object instance, DbDataReader r, PocoData pd)+MoveNext() at NPoco.Database.QueryImp[T](T instance, Expression`1 listExpression, Func`2 idFunc, Sql Sql, PocoData pocoData)+MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at Avidov.Library.Server.Database.DbHelper.Query[T](Expression`1 whereExpression) in E:\MyData\Projects\Comp\LibraryDotNet\Comp.Library\Comp.Library.Serve\Database\DbHelper.cs:line 169 at Comp.Library.Server.Database.Repositories.LessonRepository.GetNotDeletedLessons(Int32 organizationId, Int32 year) in E:\MyData\Projects\Comp\LibraryDotNet\Comp.Library\Comp.Library.Serve\Database\Repositories\LessonRepository.cs:line 76 at Comp.Library.Server.LibraryManager.LessonsNumberDaysChanged(Int32 organizationId, DateTime createdAfterDate, Int32 budgetYear) in E:\MyData\Projects\Comp\LibraryDotNet\Comp.Library\Comp.Library.Serve\LibraryManager.cs:line 81 at Comp.Library.Client.Program.Main(String[] args) in E:\MyData\Projects\Comp\LibraryDotNet\Comp.Library\Comp.Library.Client\Program.cs:line 18
解决方案
问题根源
NPoco在映射数据库字段到实体属性时,会检测实体是否实现IConvertible接口。一旦发现该接口,NPoco会调用Convert.ChangeType方法处理字段值转换,但你的Lesson类中IConvertible.ToDateTime方法直接抛出了不支持转换的异常,导致LastDate(DateTime类型)在转换时触发错误。
FirstDate未触发错误是NPoco内部映射逻辑的偶然差异(比如字段顺序、缓存机制),核心问题是IConvertible接口的错误实现干扰了NPoco的默认类型转换流程。
解决方法
方法1:移除Lesson类的IConvertible接口实现
如果业务逻辑不需要Lesson类实现IConvertible,直接移除接口及相关实现即可:
[TableName("lessons")] [PrimaryKey("id")] public class Lesson { // 保留原有属性、构造函数,删除所有IConvertible相关代码 }
方法2:正确实现IConvertible接口的ToDateTime方法
若必须保留IConvertible接口,需针对DateTime类型转换提供有效实现,避免抛出异常:
DateTime IConvertible.ToDateTime(IFormatProvider provider) { // 根据业务需求返回正确的DateTime值,若无需转换整个实体到DateTime,可调整逻辑兼容NPoco的字段转换场景 // 注意:NPoco调用Convert.ChangeType时传入的value是数据库字段值,而非Lesson实例,需匹配转换逻辑 return DateTime.Now; // 示例值,需替换为实际业务逻辑 }
额外修正:拷贝构造函数语法错误
原拷贝构造函数存在逻辑错误,应使用传入的参数对象而非类本身:
public Lesson(Lesson torahLesson) { LessonId = torahLesson.LessonId; FirstDate = torahLesson.FirstDate; LastDate = torahLesson.LastDate; }
内容的提问来源于stack exchange,提问作者user3346475
相关产品推荐
相关产品推荐

