支持 Nullable的DataReader高效轉實體代碼


    /// <summary>
    /// DataReader高性能讀取幫肋類
    /// </summary>
    public class DataReaderFullHelper
    {
        /// <summary>
        /// 讀取DataReader填充數據
        /// </summary>
        /// <typeparam name="T">實體數據體</typeparam>
        /// <param name="reader">IDataReader對像</param>
        /// <param name="autoDisposeReader">是否在讀取完成後自動釋放DataReader</param>
        /// <param name="IgnoreCase">指定匹配列表不區分大小寫</param>
        /// <returns></returns>
        public List<T> FullListFromList<T>(IDataReader reader, bool autoDisposeReader = true, bool IgnoreCase = false) where T : new()
        {
            List<T> result = new List<T>();
            try
            {

                Dictionary<int, DataColumn> columnDics = new Dictionary<int, DataColumn>();
                //表達式字典委託 
                Dictionary<int, Action<T, IDataReader>> actionDics = new Dictionary<int, Action<T, IDataReader>>();
                //數據實體類型
                Type entityType = typeof(T);
                var perDic = entityType.GetProperties().ToDictionary(p => IgnoreCase ? p.Name.ToLower() : p.Name);
                //生成表頭
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    //獲取列名
                    string colName = reader.GetName(i);
                    DataColumn col = new DataColumn()
                    {
                        ColumnName = IgnoreCase ? colName.ToLower() : colName,
                        DataType = reader.GetFieldType(i),
                        Namespace = reader.GetDataTypeName(i)
                    };
                    //添加列
                    columnDics.Add(i, col);
                    //如果包含列則進行添加
                    if (perDic.ContainsKey(col.ColumnName))
                    {
                        //獲取字典值
                        var perty = perDic[col.ColumnName];
                        bool isnullable = IsNullableType(perty.PropertyType);
                        if (isnullable)
                        {
                            actionDics.Add(i, SetValueToEntity<T>(i, perty, col.DataType, isnullable));
                        }
                        else
                        {
                            actionDics.Add(i, SetValueToEntity<T>(i, col.ColumnName, col.DataType));
                        }
                    }
                }

                //查詢讀取項
                while (reader.Read())
                {
                    T objT = new T();
                    //添加到集合
                    result.Add(objT);

                    //填充屬性值
                    foreach (var item in actionDics)
                    {
                        //判斷字段是否爲null
                        if (!reader.IsDBNull(item.Key))
                        {
                            //設置屬性值
                            item.Value(objT, reader);
                        }
                        else
                        {
                            //null處理
                        }
                    }
                }
            }
            finally
            {
                //釋放dataReader
                if (reader != null && autoDisposeReader)
                {
                    reader.Close();
                    reader.Dispose();
                }
            }
            return result;
        }


        #region 設置讀取實體屬性值
        /// <summary>
        /// nullable類型
        /// </summary>
        private Type nullableType = typeof(Nullable<>);
        /// <summary>
        /// 判斷一個類型是否爲  Nullable 值類型
        /// </summary>
        /// <param name="theType">值類型數據</param>
        /// <returns>是ull</returns>
        public bool IsNullableType(Type theType)
        {
            return (theType.IsGenericType && theType.
              GetGenericTypeDefinition().Equals
              (nullableType));
        }

        /// <summary>
        /// 返回null
        /// </summary>
        /// <typeparam name="T">值類型</typeparam>
        /// <param name="par">值數據</param>
        /// <returns></returns>
        public static Func<T, Nullable<T>> ValueAction<T>() where T : struct
        {
            Func<T, Nullable<T>> fun = val => new Nullable<T>(val);
            return fun;
        }
        /// <summary>
        /// 獲取指定索引的數據並且返回調用委託
        /// </summary>
        /// <typeparam name="T">實體類類型</typeparam>
        /// <typeparam name="T1">結果類型</typeparam>
        /// <param name="index">當前對應在DataReader中的索引</param>
        /// <param name="ProPertyName">對應實體類屬性名</param>
        /// <param name="FieldType">字段類型</param>
        /// <returns>返回通過調用的委託</returns>
        public Action<T, IDataRecord> SetValueToEntity<T>(int index, string ProPertyName, Type FieldType)
        {
            Type datareader = typeof(IDataRecord);

            IDataReader a;

            var Mdthods = datareader.GetMethods().Where(p => p.ReturnType == FieldType && p.Name.StartsWith("Get") && p.GetParameters().Where(n => n.ParameterType == typeof(int)).Count() == 1);
            //處理GetString方法
            if (FieldType == typeof(string))
            {
                Mdthods = new System.Reflection.MethodInfo[] { datareader.GetMethod("GetString") };
            }
            //獲取調用方法
            System.Reflection.MethodInfo Method = null;
            if (Mdthods.Count() > 0)
            {
                Method = Mdthods.FirstOrDefault();
            }
            else
            {
                throw new EntryPointNotFoundException("沒有從DataReader找到合適的取值方法");
            }
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            ParameterExpression r = Expression.Parameter(datareader, "r");
            //常數表達式
            ConstantExpression i = Expression.Constant(index);
            MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
            MethodCallExpression call = Expression.Call(r, Method, i);



            //instance.Property = value 這名話是重點
            BinaryExpression assignExpression = Expression.Assign(ep, call);
            var ex = Expression.Lambda(assignExpression, e, r);

            Expression<Action<T, IDataRecord>> resultEx = Expression.Lambda<Action<T, IDataRecord>>(assignExpression, e, r);
            Action<T, IDataRecord> result = resultEx.Compile();

            return result;
        }

        /// <summary>
        /// 獲取指定索引的數據並且返回調用委託,用於處理Nullable值類型值
        /// </summary>
        /// <typeparam name="T">實體類類型</typeparam>
        /// <typeparam name="T1">結果類型</typeparam>
        /// <param name="index">當前對應在DataReader中的索引</param>
        /// <param name="ProPertyName">對應實體類屬性名</param>
        /// <param name="FieldType">字段類型</param>
        /// <param name="isNnullable">是否null值</param>
        /// <returns>返回通過調用的委託</returns>
        public Action<T, IDataRecord> SetValueToEntity<T>(int index, System.Reflection.PropertyInfo ProPerty, Type FieldType, bool isNnullable)
        {

            Action<T, IDataRecord> result;
            //不是nullable正常返回
            if (!isNnullable)
            {
                result = SetValueToEntity<T>(index, ProPerty.Name, FieldType);
            }
            else
            {
                //是 nullable 需要重新計算
                Type datareader = typeof(IDataRecord);
                //獲取值類型
                var types = ProPerty.PropertyType.GetGenericArguments();
                Type valType = null;
                if (types.Length > 0)
                {
                    valType = types[0];
                }
                //這個方法是獲取值的功能
                var Mdthods = datareader.GetMethods().Where(p => p.ReturnType == valType && p.Name.StartsWith("Get") && p.GetParameters().Where(n => n.ParameterType == typeof(int)).Count() == 1);
                //處理GetString方法
                if (FieldType == typeof(string))
                {
                    Mdthods = new System.Reflection.MethodInfo[] { datareader.GetMethod("GetString") };
                }
                //獲取調用方法
                System.Reflection.MethodInfo Method = null;
                if (Mdthods.Count() > 0)
                {
                    Method = Mdthods.FirstOrDefault();
                }
                else
                {
                    throw new EntryPointNotFoundException("沒有從DataReader找到合適的取值方法");
                }
                //處理表達式
                ParameterExpression e = Expression.Parameter(typeof(T), "e");
                ParameterExpression r = Expression.Parameter(datareader, "r");
                //常數表達式
                ConstantExpression i = Expression.Constant(index);
                MemberExpression ep = Expression.PropertyOrField(e, ProPerty.Name);
                //調用dataReader的取值方法
                MethodCallExpression call = Expression.Call(r, Method, i);

                #region Nullable
                //Nullable處理
                var meth = GetType().GetMethod("ValueAction");
                var genthod = meth.MakeGenericMethod(valType);
                //調用方法生成委託
                Delegate thod = (Delegate)genthod.Invoke(null, null);
                //將委託邦定到表達式樹 new Nullable<int>(121);
                MethodCallExpression callNullable = Expression.Call(thod.Method, call);
                #endregion


                //處理值
                BinaryExpression assignExpression = Expression.Assign(ep, callNullable);
                var ex = Expression.Lambda(assignExpression, e, r);
                Expression<Action<T, IDataRecord>> resultEx = Expression.Lambda<Action<T, IDataRecord>>(assignExpression, e, r);
                result = resultEx.Compile();
            }


            return result;
        }

        /// <summary>
        /// 獲取指定索引的數據並且返回調用委託
        /// </summary>
        /// <typeparam name="T">實體類類型</typeparam>
        /// <typeparam name="T1">結果類型</typeparam>
        /// <param name="index">當前對應在DataReader中的索引</param>
        /// <param name="ProPertyName">對應實體類屬性名</param>
        /// <param name="canreturn">是否有返回值</param>
        /// <returns>返回通過調用的委託</returns>
        public Func<T, IDataReader, T1> SetValueToEntity<T, T1>(int index, string ProPertyName)
        {
            Type datareader = typeof(IDataRecord);
            var Mdthods = datareader.GetMethods().Where(p => p.ReturnType == typeof(T1));
            //獲取調用方法
            System.Reflection.MethodInfo Method = null;
            if (Mdthods.Count() > 0)
            {
                Method = Mdthods.FirstOrDefault();
            }
            else
            {
                throw new EntryPointNotFoundException("沒有從DataReader找到合適的取值方法");
            }
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            ParameterExpression r = Expression.Parameter(datareader, "r");
            //常數表達式
            ConstantExpression i = Expression.Constant(index);
            MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
            MethodCallExpression call = Expression.Call(r, Method, i);



            //instance.Property = value 這句話是重點
            BinaryExpression assignExpression = Expression.Assign(ep, call);
            var ex = Expression.Lambda(assignExpression, e, r);

            Expression<Func<T, IDataRecord, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, T1>>(assignExpression, e, r);
            Func<T, IDataRecord, T1> result = resultEx.Compile();

            return result;
        }

        /// <summary>
        /// 獲取設置DataRead與實體類指定列的表達式
        /// </summary>
        /// <typeparam name="T">實體類類型</typeparam>
        /// <typeparam name="T1">結果類型</typeparam>
        /// <param name="index">當前對應在DataReader中的索引</param>
        /// <param name="ProPertyName">對應實體類屬性名</param>
        /// <param name="DataReaderGetValueMethodName">調用DataReader中獲取值的方法名如:GetString</param>
        /// <returns>返回通過調用的委託</returns>
        public Func<T, IDataReader, T1> SetValueToEntity<T, T1>(int index, string ProPertyName, string DataReaderGetValueMethodName)
        {
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            ParameterExpression r = Expression.Parameter(typeof(IDataRecord), "r");
            //常數表達式
            ConstantExpression i = Expression.Constant(index);
            MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
            MethodCallExpression call = Expression.Call(r, typeof(IDataRecord).GetMethod(DataReaderGetValueMethodName, new Type[] { typeof(int) }), i);
            //instance.Property = value 這名話是重點
            BinaryExpression assignExpression = Expression.Assign(ep, call);
            var ex = Expression.Lambda(assignExpression, e, r);

            Expression<Func<T, IDataRecord, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, T1>>(assignExpression, e, r);
            Func<T, IDataRecord, T1> result = resultEx.Compile();

            return result;
        }

        /// <summary>
        /// 獲取設置屬性值的委託
        /// </summary>
        /// <typeparam name="T">當關類型名</typeparam>
        /// <typeparam name="T1">返回值</typeparam>
        /// <param name="index">索引</param>
        /// <param name="Entity">實體對像</param>
        /// <param name="ProPertyName">屬性名</param>
        /// <param name="DataReaderGetValueMethodName">DataReader獲取值方法名 如:"GetString"</param>
        /// <returns></returns>


        public Func<T, IDataRecord, int, T1> SetPropertyValue<T, T1>(int index, T Entity, string ProPertyName, string DataReaderGetValueMethodName)
        {


            //(e, r, index) => (e.bookname = r.GetString(index))
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            ParameterExpression r = Expression.Parameter(typeof(IDataRecord), "r");
            ParameterExpression i = Expression.Parameter(typeof(int), "index");
            MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
            MethodCallExpression call = Expression.Call(r, typeof(IDataRecord).GetMethod(DataReaderGetValueMethodName, new Type[] { typeof(int) }), i);

            //instance.Property = value 這名話是重點
            BinaryExpression assignExpression = Expression.Assign(ep, call);

            var ex = Expression.Lambda(assignExpression, e, r, i);

            Expression<Func<T, IDataRecord, int, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, int, T1>>(assignExpression, e, r, i);

            Func<T, IDataRecord, int, T1> result = resultEx.Compile();


            return result;



        }

        /// <summary>
        /// http://zhidao.baidu.com/link?url=CdGxWD3l5r9H84NPWRSBFtNkea0hn5g0YujI3AIIPUO0W6g4OHxeunQN6qW2Awq2noM2Mfnj1GrD3FOOagamtwIo67ZVK7M6hj_QiwfEJX7
        /// sdd = sdd.Where(s => s.SKUCoding.Split('-').Contains(t));
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="propertyname"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private IEnumerable<T> SearchTcontains<T>(IQueryable<T> entity, string propertyname, string value)// where T : EntityObject
        {
            //   NorthwindEntities en = new NorthwindEntities();
            ParameterExpression pe = Expression.Parameter(typeof(T), "c");
            MemberExpression me = Expression.Property(pe, "CustomerID");
            ConstantExpression ce = Expression.Constant(value);
            Expression right = Expression.Call(
            me,
                //
            typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
            ce);
            Expression<Func<T, bool>> p = Expression.Lambda<Func<T, bool>>(right, pe);

            //  IEnumerable<T> ems = en.CreateQuery<T>(Plural<T>()).Where(p);
            // return ems as IEnumerable<T>;
            return null;

        }
        #endregion
    }





使用方法:

 OracleConnection conn;
        IDataReader reader = GetReader(out conn);
        try
        {        var list= reader.ReaderToList<Entityclass>();
        }
        finally
        {
            if (reader != null)
            {
                reader.Close();
                reader.Dispose();
            }

            conn.Close();
            conn.Dispose();
        }




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章