zoukankan      html  css  js  c++  java
  • 自用的基于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

    参考资料

  • 相关阅读:
    似然函数——likelihood function
    "模式识别与机器学习"读书笔记——1.2 Probability Theory
    "模式识别与机器学习"读书笔记——1.3 Model Selection
    "模式识别与机器学习"读书笔记——1.5 Decision Theory
    C#, XML中有中文加载出错问题的处理
    如何截获浏览器的http请求——几款不错的http抓包工具
    "模式识别与机器学习"读书笔记——2 Probability Distributions
    "模式识别与机器学习"读书笔记——1.6 Information Theory
    基于TCP Socket例子
    黑客介绍跨站攻击工具XSS Shell
  • 原文地址:https://www.cnblogs.com/zyh1989/p/6253596.html
Copyright © 2011-2022 走看看