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

  • 相关阅读:
    Kubernetes 集成研发笔记
    Rust 1.44.0 发布
    Rust 1.43.0 发布
    PAT 甲级 1108 Finding Average (20分)
    PAT 甲级 1107 Social Clusters (30分)(并查集)
    PAT 甲级 1106 Lowest Price in Supply Chain (25分) (bfs)
    PAT 甲级 1105 Spiral Matrix (25分)(螺旋矩阵,简单模拟)
    PAT 甲级 1104 Sum of Number Segments (20分)(有坑,int *int 可能会溢出)
    java 多线程 26 : 线程池
    OpenCV_Python —— (4)形态学操作
  • 原文地址:https://www.cnblogs.com/hankuikui/p/8094895.html
Copyright © 2011-2022 走看看