/// <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();
}