經過表達式樹把datareader和datatable轉換爲實體

     續上兩篇文章,使用emit構造dynamic method,把 datareader轉換爲實體,以免直接使用反射來實現帶來的性能損失。代碼看似沒有紕漏,可是實際上我在framwork4下運行時,調用 dynamic method時,sql

系統都會報 「 找不到方法 ‘?’  」的錯誤,沒有找到問題所在,網上查了下資料,發如今framwork3.5以上還能夠用表達式樹動態構造 執行的語句,並動態編譯成方法。性能上與emit仍是接近,,並且代碼精簡了許多。express

廢話很少說,上代碼框架

 

 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那樣的比較大的框架,不妨考慮本身寫一個這樣的簡單的方法。.net

           List<T> list;            using (IDataReader dr = sqlCommand.ExecuteReader(sql)
            {
                list = EntityConverter.ToList<T>(dr);
            }
相關文章
相關標籤/搜索