C# 泛型通用转换:将 DataSet 转为 Model 对象
在C#开发中,经常需要将数据库查询结果(如DataSet或DataTable)映射到领域模型对象。本文分享一个基于泛型和反射的通用解决方案,能够自动将DataRow中的数据填充到任意T类型的Model实例中,简化了繁琐的手工赋值过程。
泛型转换的实现目标
在处理多层架构时,数据访问层返回的通常是数据集结构,而业务逻辑层依赖的是强类型的Model对象。手动编写映射代码不仅枯燥,还容易出错。利用泛型约束 where T : new() 和反射机制,我们可以创建一个通用的辅助类,实现从数据行到任意实体的自动化转换。
第1步:准备数据源与模型定义
假设你有一个名为 DataSet 的对象,其中包含至少一张表,且该表的列名与待转换Model类的属性名相匹配(忽略大小写通常更佳,但本例基于精确匹配)。同时,确保你的Model类包含无参构造函数,以满足泛型约束。
第2步:实现单行转换方法 PutVal
这是核心逻辑所在。该方法接收一个实体对象和一个 DataRow,通过反射获取所有 PropertyInfo,并尝试将列值赋给对应的属性。处理过程中需特别注意数据类型转换,尤其是 DateTime?(可空日期类型)的处理,以避免转换异常。
public static T PutVal<T>(T entity, DataRow row) where T : new()
{
// 初始化 如果为null
if (entity == null)
{
entity = new T();
}
// 得到类型
Type type = typeof(T);
// 取得属性集合
PropertyInfo[] pi = type.GetProperties();
foreach (PropertyInfo item in pi)
{
// 给属性赋值
// 检查列是否存在且不为空
if (row[item.Name] != null && row[item.Name] != DBNull.Value)
{
if (item.PropertyType == typeof(System.Nullable<System.DateTime>))
{
// 处理可空日期类型
item.SetValue(entity, Convert.ToDateTime(row[item.Name].ToString()), null);
}
else
{
// 使用ChangeType进行通用类型转换
item.SetValue(entity, Convert.ChangeType(row[item.Name], item.PropertyType), null);
}
}
}
return entity;
}
第3步:实现批量转换方法 PutAllVal
为了更方便地处理整个表的数据,我们提供一个外层方法。它遍历 DataSet 中第一张表的所有行,调用上述 PutVal 方法构建一个 List<T>。
public static List<T> PutAllVal<T>(T entity, DataSet ds) where T : new()
{
List<T> lists = new List<T>();
// 安全检查:确保DataSet有表且有数据
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow row in ds.Tables[0].Rows)
{
lists.Add(PutVal(new T(), row));
}
}
return lists;
}
使用注意事项与优化建议
- 性能考量:反射操作在大量数据转换时会产生一定的性能开销。对于高性能要求场景,可以考虑使用表达式树生成的动态编译代码,或使用 AutoMapper 等成熟库。
- 列名匹配:当前代码严格依赖
row[item.Name]与属性名一致。若数据库字段命名风格(如蛇形命名)与C#属性风格(驼峰命名)不一致,需添加额外的映射字典或前缀处理逻辑。 - 空值处理:代码中仅过滤了
DBNull.Value。如果数据库中存储了其他无效值(如空字符串转非空类型),可能仍会引发异常,建议在Convert.ChangeType前后增加更健壮的错误捕获。
以上就是C#实现利用泛型将DataSet转为Model的详细内容,更多关于C#数据转换技巧的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













