直接上代码:

根据属性进行映射: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. 转:docker的核心技术深度剖析

    一.docker是什么 Docker的英文本意是码头工人,也就是搬运工,这种搬运工搬运的是集装箱(Container),集装箱里面装的可不是商品货物,而是任意类型的App,Docker把App(叫Pa ...

  2. javascript 之 valueOf

    var m = { i:10, toString:function () { console.log('toString'); return this.i; }, valueOf:function ( ...

  3. sql server中的孤立用户

    此问题出现在数据库的移值上.移值后,数据库的登陆名和数据库用户名孤立,原数据中,用建立的用户名密码登陆可以访问数据库,但是移值后就不能访问了.而且如果您尝试向该登录帐户授予数据库访问权限,则会因该用户 ...

  4. Android适配不同的设备

    感谢原作者的整理: http://blog.csdn.net/chenyjays/article/details/41308887 适配不同的语言 把UI中的字符串存储在外部文件,通过代码提取. 创建 ...

  5. python 随机分类

    #encoding:utf-8import pandas as pdimport numpy as npfrom sklearn import datasets,linear_modelfrom sk ...

  6. 格式化字符串函数sprintf

    sprintf.snprintf相关函数的主要功能是把格式化的数据写入某个字符串.如最常见的应用是将整数或浮点数转换为字符串. 1.sprintf 将格式化的数据写入字符串,并自动在末尾加上一个空字符 ...

  7. python16_day23【cmdb前端】

    一.cmdb前端 https://github.com/willianflasky/growup/tree/master/s16/homework/day23_cmdb_web/s16MadKing ...

  8. Embedding SQLite in a c programm

    Embedding SQLite in a c programm        The following program demonstrates how to embed SQLite into ...

  9. PHP的pm、pm.max_requests、memory_limit

    1.php-fpm.conf中的pm pm是来控制php-fpm的工作进程数到底是一次性产生固定不变(static)还是在运行过程中随着需要动态变化(dynamic).众所周知,工作 进程数与服务器性 ...

  10. java 定时器实现

    java工程中,不免遇到需要定时处理任务的需求,有如下两种方法: 1.使用java.util.TimerTask 2.使用Quartz 一.java.util.TimerTask Timer time ...