直接上代码:

根据属性进行映射:DataTable转化成实体List

public static class DataTableExtension
{
public static List<T> ToList<T>(this DataTable dt)
{
if (dt == null || dt.Rows.Count == )
{
return null;
} List<T> entites = new List<T>(); foreach (DataRow dr in dt.Rows)
{
T t = (T)Activator.CreateInstance(typeof(T));
for (int i = ; i < dr.Table.Columns.Count; i++)
{
PropertyInfo propertyInfo = t.GetType().GetProperty(dr.Table.Columns[i].ColumnName);
if (propertyInfo != null && dr[i] != DBNull.Value)
propertyInfo.SetValue(t, dr[i], null);
} entites.Add(t);
}
return entites;
}
}
}

但是需求往往没有这么简单,如果属性名称和列名不一致,如列名是excel导入过来的,就很有可能是汉字。

我的解决办法就是,在实体模型中,添加Attribute,来注明每个属性和列名的对应关系,如下:

public class Bill
{
[Column("序号")]
public int Id { get; set; } [Column("姓名")]
public string PatientName { get; set; } [Column("结算日期")]
public DateTime BillDate { get; set; } }

现在有两种映射方式了,为了使代码不要太难看,只能重构一下:

public static class DataTableExtension
{
public static List<T> ToList<T>(this DataTable dt, IRowMapper<T> rowMapper)
{
if (dt == null || dt.Rows.Count == )
{
return null;
} List<T> entites = new List<T>(); foreach (DataRow dr in dt.Rows)
{
var t = rowMapper.MapRow(dr); entites.Add(t);
}
return entites;
}
}

添加了一个接口IRowMapper,表明是属性映射,还是自定义的映射。

来看下自定义映射具体的实现:

public class ColumnAttributeMapper<T> : IRowMapper<T>
{
private static Dictionary<string, Dictionary<string, string>> ColumnPropertyMapper= new Dictionary<string, Dictionary<string, string>>(); public ColumnAttributeMapper()
{
if (!ColumnPropertyMapper.ContainsKey(typeof(T).Name))
{
Dictionary<string, string> dict = new Dictionary<string, string>(); var props = typeof(T).GetProperties(); foreach (var prop in props)
{
var attribute = prop.GetCustomAttributes(true).OfType<ColumnAttribute>().FirstOrDefault();
dict.Add(attribute.Name, prop.Name); }
ColumnPropertyMapper.Add(typeof(T).Name, dict);
} } public T MapRow(DataRow dr)
{
T t = (T)Activator.CreateInstance(typeof(T));
for (int i = ; i < dr.Table.Columns.Count; i++)
{
if (ColumnPropertyMapper.ContainsKey(t.GetType().Name))
{
var dict = ColumnPropertyMapper[t.GetType().Name];
var property = dict[dr.Table.Columns[i].ColumnName]; PropertyInfo propertyInfo = t.GetType().GetProperty(property);
if (propertyInfo != null && dr[i] != DBNull.Value)
propertyInfo.SetValue(t, dr[i], null);
}
} return t;
}
}

在构造函数中定义了一个静态的字典,用于存储实体中列名和属性名的对应关系(这里有点绕,我还没想到更好的方法!),

具体调用方法:

  public static void TestPropertyMapper()
{
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("PatientName", typeof(string));
dt.Columns.Add("BillDate", typeof(DateTime)); dt.Rows.Add(, "HKK", DateTime.Now);
dt.Rows.Add(, "WQ", DateTime.Now);
dt.Rows.Add(, "HS", DateTime.Now); List<Bill> bills = dt.ToList<Bill>(rowMapper: new PropertyColumnMapper<Bill>());
}
private static void TestColumnMapper()
{
DataTable dt = new DataTable();
dt.Columns.Add("序号", typeof(int));
dt.Columns.Add("姓名", typeof(string));
dt.Columns.Add("结算日期", typeof(DateTime)); dt.Rows.Add(, "HKK", DateTime.Now);
dt.Rows.Add(, "WQ", DateTime.Now);
dt.Rows.Add(, "HS", DateTime.Now); List<Bill> bills = dt.ToList<Bill>(rowMapper: new ColumnAttributeMapper<Bill>());
}

代码上传到github:https://github.com/hankuikuide/ExcelAccessor/tree/master/Han.DataAccess

DataTable扩展:转化实体ToList的更多相关文章

  1. DataTable数据转换为实体

    我们在用三层架构编写软件时,常常会遇到例如以下问题,就是三层之间的參数传递问题:假设我们在D层查询出数据是DataTable类型的,那么我们在B层甚至U层使用这条数据时,就要用DataTable类型来 ...

  2. DataTable转换为Model实体对象

    记得在学校的时候,接触得最多的就是SqlHelper,每次在读取的时候不管是DataTable还是DataReader转换为实体对象的时候是最恼火的,因为要写很多代码,而且没有什么意义.后面接触到了反 ...

  3. C# DataTable转换成实体列表 与 实体列表转换成DataTable

    /// <summary> /// DataTable转换成实体列表 /// </summary> /// <typeparam name="T"&g ...

  4. DataTable扩展方法ToList<T>()、ToJSON()、ToArrayList()

    /// <summary> /// 扩展方法类 /// </summary> public static class CommonExtension { /// <sum ...

  5. DataTable填补了实体类返回泛型集合

    坤哥见我昨天找了一段代码,如下面: 略微解释下,这段代码时D层查询结束后,将datatable查询到的结果赋值给实体对象的属性,然后返回实体的过程.坤哥看了之后问我,假设实体有500多个属性,难道也要 ...

  6. C#把 DataTable转换为Model实体

    public static List<T> GetModelFromDB<T>( DataTable dt ) { List<T> data = new List& ...

  7. (转)DATATABLE(DATASET)与实体类之间的互转.

    转自:http://www.cnblogs.com/zzyyll2/archive/2010/07/20/1781649.html dataset和实体类 之间的转换 //dataset转实体类  代 ...

  8. DataTable转换成实体

    public static class DataTableToEntity { /// <summary> /// 将DataTable数据源转换成实体类 /// </summary ...

  9. C# DataTable扩展方法

    在日常搬砖中,总结了一些简单的扩展方法. public static bool IsNullOrEmpty(this DataTable dt) { ; } public static bool Is ...

随机推荐

  1. 利用wget批量下载http目录下文件

    原理:下载你需要down的目录页面的index.html,可能名字不是如此!!!之后用wget下载该文件里包含的所有链接! 例如:wget -vE -rLnp -nH --tries=20 --tim ...

  2. SpringBean 定义继承

    Bean定义继承 bean定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等.子bean的定义继承副定义的配置数据.子定义可以根据需要重写一些值 ...

  3. wordpress 主题开发

    https://yusi123.com/3205.html https://themeshaper.com/2012/10/22/the-themeshaper-wordpress-theme-tut ...

  4. yii2 框架中的即点即改入库

    视图层 <td><span class='num'  id="<?php echo $value['goods_attr_id']?>">< ...

  5. 300. Longest Increasing Subsequence(LIS最长递增子序列 动态规划)

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  6. NGUI混合FingerGesture《卷二》分离触摸事件

    背景 在使用NGUI按钮组件的时候,点击按钮同时触发FingerGesture的Touch事件, 通俗点讲,NGUI点击之后,点击事件被FingerGesture又执行了一遍. 解决思路 持有一个全局 ...

  7. 有界、无界队列对ThreadPoolExcutor执行的影响

    本文转载自https://blog.csdn.net/kusedexingfu/article/details/72491864 Java提供了4钟线程池: newCachedThreadPool n ...

  8. RedisTemplate访问Redis数据结构

    https://www.jianshu.com/p/7bf5dc61ca06 Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字 ...

  9. servlet的总结

    tomcat在启动的时候 加载webapp下面的web.xml,加载里面定义的servlet. web.xml文件有两部分:servlet类定义和servlet映射定义每个被载入的servlet类都有 ...

  10. 20145307第八周JAVA学习报告

    20145307<Java程序设计>第8周学习总结 教材学习内容总结 通用API 日志API 1.java.util.logging包提供了日志功能相关类与接口,使用日志的起点是logge ...