• DataTable数据赋值给Model通用方法


    注:该文属本人原创,今后项目中发现该方法存在BUG会实时更新,转载记得附上原文出处,方便大家获得最新代码。

    相信大家在做项目中,经常会根据不同的表new各种不同的Model,当需要对Model进行实例化的时候,先将数据从数据库取出,将该数据中的每个值都赋值给一个model,假如你有10个Model,每次都会从不同的表中获取数据,需要处理的数据完全不同,那么就要写10个方法,对着10个Model进行赋值。编码效率又低又low。为提高代码通用性,故写了个通用方法,实现datatable赋值model。

    表结构(只是为了做演示,故没有对表中列属性进行相关设置,默认都允许为null):

    CREATE TABLE [AddressInfo](
        [Name] [NVARCHAR](20) NULL,
        [Sex] [NVARCHAR](2) NULL,
        [Address] [NVARCHAR](50) NULL,
        [Age] [INT] NULL,
        [Birthday] [DATE] NULL
    ) 

    Model类:

     1 public class AddressInfoModel
     2     {
     3 
     4         /// <summary>
     5         /// 姓名
     6         /// </summary>
     7         public string Name { get; set; }
     8         /// <summary>
     9         /// 性别
    10         /// </summary>
    11         public string Sex { get; set; }
    12         /// <summary>
    13         /// 地址
    14         /// </summary>
    15         public string Address { get; set; }
    16         /// <summary>
    17         /// 年龄
    18         /// </summary>
    19         public int? Age { get; set; }
    20         /// <summary>
    21         /// 生日
    22         /// </summary>
    23         public DateTime? Birthday { get; set; }
    24 
    25     }

    通常我们得到Model实体是这样进行的

     1         /// <summary>  
     2         /// 得到一个对象实体
     3         /// </summary>
     4         public AddressInfo DataRowToModel(DataRow row)
     5         {
     6             Maticsoft.Model.addressinfo model=new Maticsoft.Model.addressinfo();
     7             if (row != null)
     8             {
     9                 if(row["id"]!=null && row["id"].ToString()!="")
    10                 {
    11                     model.id=int.Parse(row["id"].ToString());
    12                 }
    13                 if(row["name"]!=null)
    14                 {
    15                     model.name=row["name"].ToString();
    16                 }
    17                 if(row["Sex"]!=null)
    18                 {
    19                     model.Sex=row["Sex"].ToString();
    20                 }
    21                 if(row["Address"]!=null)
    22                 {
    23                     model.Address=row["Address"].ToString();
    24                 }
    25                 if(row["Age"]!=null && row["Age"].ToString()!="")
    26                 {
    27                     model.Age=int.Parse(row["Age"].ToString());
    28                 }
    29                 if(row["Birthday"]!=null && row["Birthday"].ToString()!="")
    30                 {
    31                     model.Birthday=DateTime.Parse(row["Birthday"].ToString());
    32                 }
    33             }
    34             return model;
    35         }
    36      

    相信这是大家常用的方法,该方法的好处是简单,容易理解,但是这样写会存在一个弊端,那就是方法通用性极差,甚至根本就没有通用性,而且日后也不易维护。

    试想一下:

    (1)如果我们有100个Model需要赋值,按照这样来做,我们岂不是需要写100个这样的方法来进行Model的赋值?

    (2)一旦其中Model属性发生改变,那么对应的方法也必须发生相应的修改,如果客户不断提出改变要对Model属性进行修改,那工作量岂不是很大?

    天哪!这工作量简直不敢想象。

    通过对上面的思考,我们不难发现,不管有多少个Model其实在对其进行赋值时,所进行的逻辑处理都是有规律的重复性的工作,即将DataRow中的列赋值给对应Model属性。

    经过一番努力终于通用方法第一个版本出炉(废话不多说直接上干货!)

    (1)DataRow赋值Model通用方法之版本一:(该方法淘汰,仅为大家提供思路)

     1         /// <summary>
     2         /// 将DataRow中数据赋值给model中的同名属性
     3         /// </summary>
     4         /// <typeparam name="T">泛型:model的类型</typeparam>
     5         /// <param name="objmodel">model的实例</param>
     6         /// <param name="dtRow">DataRow</param>
     7         public T TableToModel<T>(T objmodel, DataRow dtRow)
     8         {
     9             //获取model的类型
    10             Type modelType = typeof(T);
    11             //获取model中的属性
    12             PropertyInfo[] modelpropertys = modelType.GetProperties();
    13             //遍历DataTable的每一列
    14             //遍历model的每一个属性
    15             foreach (PropertyInfo pi in modelpropertys)
    16             {
    17                 //获取属性名称
    18                 String name = pi.Name;
    19                 //将DataRow中数据赋值给model中的同名属性(不区分属性名称大小写name和Name效果一样)
    20                 if (dtRow.Table.Columns.Contains(name)) 
    21                 {
    22                     object value = dtRow[name].ToString();
    23                     pi.SetValue(objmodel, value, null);
    24                 }
    25             }
    26         }

    通过测试发现,该方法对于Model属性都是string类型的没有问题,该Model中Age为Int类型,Birthday为DateTime类型,会发生类型不能匹配的错误,故通用性极差。在此基础上出现了通用版本二

    (2)DataRow赋值Model通用方法之版本二:(该方法淘汰,仅为大家提供思路)

    将22行代码
    22 object value = dtRow[name].ToString();
    修改为
    object value = Convert.ChangeType(dtRow[name], modelType.GetProperty(name).PropertyType);
    解决DataRow类型与Model类型不匹配问题

    此时,该方法已经很好的通用性,着实高兴了一下,但是当测试中,数据库中自读允许为null的情况下,该方法便不能适应复杂多变的Model赋值。例如该类中年龄和出生年月字段是允许为空的
    即 int? Age 和DateTime? Birthday会报错,不能将null值赋值给指定的数据类型,因为进一步改进该方法,最终版本如下:

    (3)DataRow赋值Model通用方法之最终版:
     1         /// <summary>
     2         /// 将DataRow赋值给model中同名属性
     3         /// </summary>
     4         /// <typeparam name="T">泛型:model的类型</typeparam>
     5         /// <param name="objmodel">model实例</param>
     6         /// <param name="dtRow">DataTable行数据</param>
     7         public T TableRowToModel<T>(T objmodel, DataRow dtRow)
     8         {
     9             //获取model的类型
    10             Type modelType = typeof(T);
    11             //获取model中的属性
    12             PropertyInfo[] modelpropertys = modelType.GetProperties();
    13             //遍历model每一个属性并赋值DataRow对应的列
    14             foreach (PropertyInfo pi in modelpropertys)
    15             {
    16                 //获取属性名称
    17                 String name = pi.Name;
    18                 if (dtRow.Table.Columns.Contains(name))
    19                 {
    20                     //非泛型
    21                     if (!pi.PropertyType.IsGenericType)
    22                     {
    23                         pi.SetValue(objmodel, string.IsNullOrEmpty(dtRow[name].ToString()) ? null : Convert.ChangeType(dtRow[name], pi.PropertyType), null);
    24                     }
    25                     //泛型Nullable<>
    26                     else
    27                     {
    28                         Type genericTypeDefinition = pi.PropertyType.GetGenericTypeDefinition();
    29                         //model属性是可为null类型,进行赋null值
    30                         if (genericTypeDefinition == typeof(Nullable<>))
    31                         {
    32                            //返回指定可以为 null 的类型的基础类型参数
    33                            pi.SetValue(objmodel, string.IsNullOrEmpty(dtRow[name].ToString()) ? null : Convert.ChangeType(dtRow[name], Nullable.GetUnderlyingType(pi.PropertyType)), null);
    34                         }
    35                     }
    36                 }
    37             }
    38             return objmodel;
    39         }
    
    
    最终实现DataRow数据赋值给Model

    通过该方法便可简单实现将DataTable赋值给List<Model>!!(此处便不再给大家演示)


  • 相关阅读:
    System.IO.StreamWriter
    C# XML
    C# 泛型
    ACM将一个十进制的数转换为一个十六进制的数输出
    ACM打扫花园问题
    ACM用N个正方体来建造金字塔问可以建造多少层
    输入一串数字找出其中缺少的最小的两个数
    高效算法——B 抄书 copying books,uva714
    暴力求解——POJ 3134Power Calculus
    暴力求解——打表,暴力
  • 原文地址:https://www.cnblogs.com/xinlj/p/5113396.html
Copyright © 2020-2023  润新知