C#怎么将DataTable转换为List C#数据表转泛型列表方法

3次阅读

C# 中 DataTable 转 List 推荐反射通用法:属性名与列名不区分大小写匹配,自动处理基础类型及可 空类型 ,跳过不匹配列和 DBNULL 值;linq法简洁但需手动处理 类型转换 和 DBNull。

C# 怎么将 DataTable 转换为 List C# 数据表转泛型列表方法

在 C# 中,将 DataTable 转换为 泛型 List<t></t> 是常见需求,核心思路是:** 通过反射获取目标类型 T 的属性,逐行读取 DataTable 的数据并映射赋值 **。关键在于字段名与属性名的匹配、类型转换的安全处理,以及 性能优化

使用反射 + 泛型方法(推荐,通用性强)

这是最常用、可复用的方式,适合大多数自定义实体类:

  • 要求实体类属性名与 DataTable 列名(ColumnName)完全一致(不区分大小写更稳妥)
  • 自动处理基础类型(intString、DateTime 等)和可空类型(int?、DateTime?)
  • 跳过不匹配的列或无法转换的值,避免运行时异常

示例代码:

public static List<T> ToList<T>(DataTable dt) where T : new() {     var list = new List<T>();     var properties = typeof(T).GetProperties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); <pre class="brush:php;toolbar:false;">foreach (DataRow row in dt.Rows) {var obj = new T();     foreach (var prop in properties.Values)     {if (dt.Columns.Contains(prop.Name) && row[prop.Name] != DBNull.Value)         {try             {var value = Convert.ChangeType(row[prop.Name], prop.PropertyType);                 prop.SetValue(obj, value);             }             catch {/* 类型不兼容时跳过该字段 */}         }     }     list.Add(obj); } return list;

}

调用方式:var users = ToList<user>(dataTable);</user>

使用 LINQ + DataRowExtensions(.net Framework 3.5+ / .NET Core 3.0+)

如果 DataTable 结构固定、实体简单,可用更简洁的 LINQ 写法:

  • 依赖 System.Data.DataSetExtensions(需引用对应 NuGet 包或框架内置)
  • 适合快速原型或单次转换,可读性高
  • 需手动处理类型转换和 DBNull,灵活性略低

示例:

var list = dataTable.AsEnumerable()     .Select(row => new User     {         Id = row.Field<int>("Id"),         Name = row.Field<string>("Name"),         BirthDate = row.Field<DateTime?>("BirthDate")     }).ToList();

注意字段映射与类型安全

实际使用中容易出错的点:

  • 列名大小写敏感:DataTable 列名默认区分大小写,建议用 StringComparer.OrdinalIgnoreCase 或统一转小写比对
  • DBNull 处理:必须检查 row[colName] != DBNull.Value,否则 Convert.ChangeType 会抛异常
  • 可空类型支持:如 int?,要确保源值为 null 或能转为目标基础类型,Field<t>()</t> 方法内部已处理
  • 日期 / 时间格式 数据库 中可能存 字符串,需提前清洗或自定义转换逻辑

性能优化小提示

大数据 量时可提升效率:

  • 预先缓存 PropertyInfo[] 和列索引(如 dt.Columns.IndexOf("Name")),避免每次 循环 重复查找
  • foreach (DataRow row in dt.Rows)for (int i = 0; i 更高效(DataTable 内部做了优化)
  • 若确定无 DBNull 且类型严格匹配,可省略 try-catch,但务必确保数据质量

基本上就这些。选反射通用版还是 LINQ 简洁版,取决于你的项目规范、数据稳定性和维护成本。不复杂但容易忽略细节,尤其在跨数据库或历史数据迁移场景下。

站长
版权声明:本站原创文章,由 站长 2025-12-18发表,共计1761字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
1a44ec70fbfb7ca70432d56d3e5ef742
text=ZqhQzanResources