自用的基于Emit的C#下DataTable转实体类方法

来源:互联网 发布:淘宝哪些店铺布料便宜 编辑:程序博客网 时间:2024/05/24 06:06

自用的基于Emit的C#下DataTable转实体类方法

之前一直在做WebForm的开发,数据绑定时直接DataTable绑定Gridview很方便,但是最近开始往MVC转,数据列表的传递和页面展示基本上是以List为主,像下面这样,遍历实体类的各个字段去赋值的办法当然是最浪费时间的。

            if (row["ID"] != null && row["ID"].ToString() != "")            {                model.bedID = int.Parse(row["ID"].ToString());            }

通过在网上查资料和一定的比较,我选择了以下基于Emit的DataTable转实体类的方法。
按照下边的代码新建一个类EntityConverter:

  public static class EntityConverter  {        public static List<T> ToList<T>(this DataTable dt) where T : class, new()        {            List<T> list = new List<T>();            if (dt == null || dt.Rows.Count == 0)                return list;            DataTableEntityBuilder<T> eblist = DataTableEntityBuilder<T>.CreateBuilder(dt.Rows[0]);            foreach (DataRow info in dt.Rows)                list.Add(eblist.Build(info));            dt.Dispose();            dt = null;            return list;        }        public class DataTableEntityBuilder<Entity>        {            private static readonly MethodInfo getValueMethod = typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) });            private static readonly MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) });            private delegate Entity Load(DataRow dataRecord);            private Load handler;            private DataTableEntityBuilder() { }            public Entity Build(DataRow dataRecord)            {                return handler(dataRecord);            }            public static DataTableEntityBuilder<Entity> CreateBuilder(DataRow dataRecord)            {                DataTableEntityBuilder<Entity> dynamicBuilder = new DataTableEntityBuilder<Entity>();                DynamicMethod method = new DynamicMethod("DynamicCreateEntity", typeof(Entity), new Type[] { typeof(DataRow) }, typeof(Entity), true);                ILGenerator generator = method.GetILGenerator();                LocalBuilder result = generator.DeclareLocal(typeof(Entity));                generator.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes));                generator.Emit(OpCodes.Stloc, result);                for (int i = 0; i < dataRecord.ItemArray.Length; i++)                {                    PropertyInfo propertyInfo = typeof(Entity).GetProperty(dataRecord.Table.Columns[i].ColumnName);                    Label endIfLabel = generator.DefineLabel();                    if (propertyInfo != null && propertyInfo.GetSetMethod() != null)                    {                        generator.Emit(OpCodes.Ldarg_0);                        generator.Emit(OpCodes.Ldc_I4, i);                        generator.Emit(OpCodes.Callvirt, isDBNullMethod);                        generator.Emit(OpCodes.Brtrue, endIfLabel);                        generator.Emit(OpCodes.Ldloc, result);                        generator.Emit(OpCodes.Ldarg_0);                        generator.Emit(OpCodes.Ldc_I4, i);                        generator.Emit(OpCodes.Callvirt, getValueMethod);                        generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);                        generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());                        generator.MarkLabel(endIfLabel);                    }                }                generator.Emit(OpCodes.Ldloc, result);                generator.Emit(OpCodes.Ret);                dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));                return dynamicBuilder;            }        }  }

在DbHelperSQL里面再简单封装一下:

      public static List<T> Query<T>(string sql) where T : class, new()        {            DataTable dt = DbHelperSQL.Query(sql).Tables[0];            if (dt != null && dt.Rows.Count > 0)            {                return EntityConverter.ToList<T>(dt);            }            else            {                return null;            }         }

使用的时候:

    string sql="select top 10 * from user";    List<Model.User> listUser=DbHelperSQL.Query<Model.User>(sql);

注意:
- 1、定义的Model的各个属性的名称要和Select语句执行结果的列名一致
- 2、定义的Model的各个属性的数据类型要和数据库定义的一致
- 3、关于数据列与属性对应:Model中的属性SQL里面可以没有,值会默认为Null/0;但是SQL结果里面有的列名必须在Model中存在。否则会报错!

这只是简单的使用,更深层次的需求请参考再谈使用Emit把Datatable转换为对象集合(List) - lindping
原文链接 http://huisky.com/blog/17010514150692
参考资料
- DataTable转Entity(Emit版) - ShuLin
- 使用Emit把Datatable转换为对象集合(List) - lindping
- 再谈使用Emit把Datatable转换为对象集合(List) - lindping

0 0
原创粉丝点击