随笔 - 35  文章 - 0  评论 - 121  阅读 - 56623

通过表达式树把datareader和datatable转换为实体

     续上两篇文章,使用emit构造dynamic method,把 datareader转换为实体,以避免直接使用反射来实现带来的性能损失。代码看似没有纰漏,但是实际上我在framwork4下运行时,调用 dynamic method时,

系统都会报 “ 找不到方法 ‘?’  ”的错误,没有找到问题所在,网上查了下资料,发现在framwork3.5以上还可以用表达式树动态构造 执行的语句,并动态编译成方法。性能上与emit还是接近,,而且代码精简了许多。

废话不多说,上代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class EntityConverter
   {
       public static Action<T, object> GetSetter<T>(PropertyInfo  property)
       {
           Action<T, object> result = null;
           Type type = typeof(T);          
           string key = type.AssemblyQualifiedName + "_set_" + property.Name;
           if (HttpRuntime.Cache.Get(key) == null)
           {
 
               //创建 对实体 属性赋值的expression
               ParameterExpression parameter = Expression.Parameter(type, "t");
               ParameterExpression value = Expression.Parameter(typeof(object), "propertyValue");
               MethodInfo setter = type.GetMethod("set_" + property.Name);
               MethodCallExpression call = Expression.Call(parameter, setter, Expression.Convert(value, property.PropertyType));
               var lambda = Expression.Lambda<Action<T, object>>(call, parameter, value);
               result = lambda.Compile();
               HttpRuntime.Cache[key] = result;
           }
           else
           {
               result =  HttpRuntime.Cache[key] as Action<T, object>;
           }       
            return result;
       }
 
       public static List<T> ToList<T>(DataTable dt) where T : new()
       {
           List<T> list = new List<T>();
           if (dt == null || dt.Rows.Count == 0)
           {
               return list;
           }  
 
           foreach (DataRow dr in dt.Rows)
           {
               T t= new T();
               foreach (PropertyInfo prop in typeof(T).GetProperties())
               {
                   if (dr.Table.Columns.Contains(prop.Name))
                   {
                       GetSetter<T>(prop)(t, dr[prop.Name]);
                   }
               }
               list.Add(t);
           }      
 
           return list;
       }
 
       public static List<T> ToList<T>(IDataReader dr) where T:new()
       {
           List<T> list = new List<T>();       
           while (dr.Read())
           {
               T t = new T();
               foreach (PropertyInfo prop in typeof(T).GetProperties())
               {                
                       GetSetter<T>(prop)(t, dr[prop.Name]);               
               }
               list.Add(t);
           }
           return list;
       }
 
   }

  

代码还稍微有点粗糙,还可以细化一下,比如 datatable和datareader的字段名称,和对应实体的属性名,可以忽略大小写,目前我的代码是区分的,有兴趣的可以自己优化。

如果你看完了我写的文字还代码,还是一头雾水,可以看看我的上两篇博文。简单说 就是类似orm的核心功能,把通过ado.net组件查询到的数据(datatable,datareader)转换为实体列表 List<T>,

如果你的代码框架还比较古老,又不愿意引入诸如EF,Nhibernate那样的比较大的框架,不妨考虑自己写一个这样的简单的方法。

           List<T> list;
using (IDataReader dr = sqlCommand.ExecuteReader(sql) { list = EntityConverter.ToList<T>(dr); }

 

posted on   lindping  阅读(795)  评论(6编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示