You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现泛型数据库读取方法GetDataMethod<T>报类型转换错误求解

问题原因

你的代码存在核心逻辑错误,才会触发两类类型转换异常:

  • 当前读取到的tempRow是object[]类型,仅存储了一行数据库记录的原始字段值,没有任何将字段值映射到T类型实例的逻辑,直接把object[]加入List<T>必然会报类型不匹配错误。
  • 出现的"System.String无法转换为MyBooks.Data.Model.Book"报错,是因为尝试直接将单个数据库字段值(比如字符串类型的书名、作者字段)强转为Book类型,本质同样是缺失字段到实体属性的映射步骤。
  • 原代码没有做数据库资源释放,长时间运行会耗尽连接池资源。
修复方案

给泛型加new()约束保证可以实例化实体,通过反射做字段和实体属性的映射,同时处理空值、可空类型转换问题,修正后的可直接运行的代码如下:

using System.Data;
using System.Reflection;

public List<T> GetDataMethod<T>(SqlCommand cmd) where T : new()
{
    List<T> records = new List<T>();
    // using块自动释放连接、读取器资源,避免资源泄漏
    using (SqlConnection conn = getcon())
    {
        cmd.Connection = conn;
        conn.Open();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            // 提前缓存实体属性映射,减少循环内重复反射的性能损耗
            Dictionary<string, PropertyInfo> propertyMap = typeof(T)
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .ToDictionary(p => p.Name, p => p, StringComparer.OrdinalIgnoreCase);

            while (reader.Read())
            {
                T entity = new T();
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    string columnName = reader.GetName(i);
                    object columnValue = reader[i];
                    // 匹配到对应属性、属性可写、字段值非空时执行赋值
                    if (propertyMap.TryGetValue(columnName, out PropertyInfo prop) 
                        && prop.CanWrite 
                        && columnValue != DBNull.Value)
                    {
                        // 处理int?、DateTime?这类可空值类型的转换
                        Type targetType = prop.PropertyType;
                        if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            targetType = Nullable.GetUnderlyingType(targetType);
                        }
                        prop.SetValue(entity, Convert.ChangeType(columnValue, targetType));
                    }
                }
                records.Add(entity);
            }
        }
    }
    return records;
}
使用说明
  • 调用方法时直接传入实体类作为泛型参数即可,比如查询Book列表就写GetDataMethod<Book>(yourSqlCmd)
  • 映射逻辑默认按忽略大小写的属性名/字段名匹配,比如数据库返回字段book_id无法自动匹配BookId属性,写SQL时需要给字段起和实体属性同名的别名,或者自行扩展自定义映射特性。
  • 如果项目有复杂查询、性能要求高的场景,不建议自己手写反射映射,直接用Dapper这类轻量ORM即可,内置的泛型查询逻辑已经覆盖了所有边界场景,性能也比手写反射好很多。

内容的提问来源于stack exchange,提问作者M. Rizwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 03:51:23