zoukankan      html  css  js  c++  java
  • DataTable扩展:转化实体ToList

    直接上代码:

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

    public static class DataTableExtension
        {
            public static List<T> ToList<T>(this DataTable dt)
            {
                if (dt == null || dt.Rows.Count == 0)
                {
                    return null;
                }
    
                List<T> entites = new List<T>();
    
                foreach (DataRow dr in dt.Rows)
                {
                    T t = (T)Activator.CreateInstance(typeof(T));  
                    for (int i = 0; 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 == 0)
                {
                    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 = 0; 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(1, "HKK", DateTime.Now);
                dt.Rows.Add(2, "WQ", DateTime.Now);
                dt.Rows.Add(3, "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(1, "HKK", DateTime.Now);
                dt.Rows.Add(2, "WQ", DateTime.Now);
                dt.Rows.Add(3, "HS", DateTime.Now);
    
                List<Bill> bills = dt.ToList<Bill>(rowMapper: new ColumnAttributeMapper<Bill>());
            }

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

  • 相关阅读:
    淘淘商城-day02[框架整合,后台系统搭建]
    淘淘商城-day01[项目介绍,搭建maven工程,SVN使用]
    CentOS7安装FastDFS 5.05
    ubuntu ssh 开启
    BAT 快速删除CVS文件和拷贝最近修改文件的目录结构
    eclipse 插件
    Eclipse 工作空间目录 详解
    淘淘商城-传智播客J2EE的实践项目 目录篇
    eclipse 版本 发行版本
    ROM、PROM、EPROM、EEPROM、Flash ROM分别指什么?
  • 原文地址:https://www.cnblogs.com/hankuikui/p/8094895.html
Copyright © 2011-2022 走看看