·您现在的位置: 江北区云翼计算机软件开发服务部 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 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>!!(此处便不再给大家演示)