使用反射读取SQL值并赋值正确数据类型的方案可行性问询
你的实现思路是可行的,但直接运行会遇到多个潜在问题,具体如下:
核心问题列表
- 可空类型转换报错:
Convert.ChangeType原生不支持直接转换为Nullable<>可空类型,比如你要映射到int?、bool?这类属性时,会直接抛出InvalidCastException异常,它只能识别int、bool这类基础值类型。 - 数据库空值未处理:SQL查询返回的空值是
DBNull.Value,不是C#原生的null,直接传入Convert.ChangeType也会触发转换失败的异常。 - 冗余代码问题:你已经用
using包裹了SqlDataReader实例,离开作用域时会自动释放并关闭连接,手动调用reader.Close()属于多余操作,完全可以删掉。 - 类型映射偏差风险:如果SQL字段类型和C#属性类型不严格匹配,比如SQL的
tinyint对应C#的byte、smallint对应short,没有做适配的情况下也会偶发转换异常。
修复后的可用代码
AdressEntries client = new AdressEntries(); Type t = client.GetType(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { client = new AdressEntries(); foreach (PropertyInfo variable in t.GetProperties()) { object dbValue = reader[variable.Name]; // 处理数据库返回的空值 if (dbValue == DBNull.Value) { variable.SetValue(client, null); continue; } // 提取可空类型的底层实际类型 Type targetType = variable.PropertyType; Type underlyingType = Nullable.GetUnderlyingType(targetType); if (underlyingType != null) { targetType = underlyingType; } // 完成类型转换后赋值 object convertedValue = Convert.ChangeType(dbValue, targetType); variable.SetValue(client, convertedValue); } allClients.Add(client); } }
额外注意事项
- 要保证C#类的属性名和SQL查询返回的字段名完全一致,否则
reader[variable.Name]会抛出找不到对应字段的异常 - 如果涉及
DateTimeOffset、TimeSpan这类特殊类型,Convert.ChangeType无法直接转换,需要额外加判断逻辑做特殊适配 - 如果需要更高的性能,你可以提前缓存类型的属性信息和转换逻辑,不用每次都反射读取属性列表
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

