动态实体绑定 主要有以下两种
1、表达式树构建委托
2、Emit构建委托
根据我的经验 Emit 代码量可以更少可以很好实现代码复用
Emit实践开源项目地址跳转 https://www.cnblogs.com/China-Mr-zhong/p/17514567.html 查看
c#
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
namespace Fast.Framework.Extensions
{
/// <summary>
/// 可空扩展类
/// </summary>
public static class NullableExtensions
{
/// <summary>
/// 到Nullable
/// </summary>
private static readonly Dictionary<Type, MethodInfo> toNullableCache;
/// <summary>
/// 构造方法
/// </summary>
static NullableExtensions()
{
toNullableCache = new Dictionary<Type, MethodInfo>()
{
{ typeof(short),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(short) })},
{ typeof(ushort),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(ushort) })},
{ typeof(int),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(int) })},
{ typeof(uint),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(uint) })},
{ typeof(long),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(long) })},
{ typeof(ulong),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(ulong) })},
{ typeof(float),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(float) })},
{ typeof(double),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(double) })},
{ typeof(decimal),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(decimal) })},
{ typeof(char),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(char) })},
{ typeof(byte),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(byte) })},
{ typeof(sbyte),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(sbyte) })},
{ typeof(bool),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(bool) })},
{ typeof(string),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(string) })},
{ typeof(DateTime),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(DateTime) })},
{ typeof(DateTimeOffset),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(DateTimeOffset) })},
{ typeof(TimeSpan),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(TimeSpan) })},
{ typeof(Guid),typeof(NullableExtensions).GetMethod(nameof(ToNullable), new Type[] { typeof(Guid) })},
};
}
/// <summary>
/// 获取ToNullable方法信息
/// </summary>
/// <param name="type">类型</param>
/// <returns></returns>
public static MethodInfo GetToNullableMethodInfo(this Type type)
{
if (!toNullableCache.ContainsKey(type))
{
throw new NotSupportedException($"类型:{type.Name}暂不支持转换");
}
return toNullableCache[type];
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static short? ToNullable(short value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static ushort? ToNullable(ushort value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static int? ToNullable(int value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static uint? ToNullable(uint value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static long? ToNullable(long value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static ulong? ToNullable(ulong value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static float? ToNullable(float value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static double? ToNullable(double value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static decimal? ToNullable(decimal value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static char? ToNullable(char value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static byte? ToNullable(byte value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static sbyte? ToNullable(sbyte value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static bool? ToNullable(bool value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static DateTime? ToNullable(DateTime value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static DateTimeOffset? ToNullable(DateTimeOffset value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static TimeSpan? ToNullable(TimeSpan value)
{
return value;
}
/// <summary>
/// 到Nullable
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
public static Guid? ToNullable(Guid value)
{
return value;
}
}
}
c#
using System;
using System.Text;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using Fast.Framework.Cache;
using System.Data;
using Fast.Framework.Utils;
using System.Text.Json;
using Fast.Framework.Exceptions;
using Fast.Framework.Models;
using System.Reflection.Emit;
namespace Fast.Framework.Extensions
{
/// <summary>
/// DbDataReader扩展类
/// </summary>
public static class DbDataReaderExtensions
{
/// <summary>
/// 获取方法信息缓存
/// </summary>
private static readonly Dictionary<Type, MethodInfo> getMethodInfoCache;
/// <summary>
/// 转换方法信息
/// </summary>
private static readonly Dictionary<Type, ConvertInfo> convertMethodInfos;
/// <summary>
/// 是否DBNull方法信息
/// </summary>
private static readonly MethodInfo isDBNullMethodInfo;
/// <summary>
/// 是否空或空格字符串方法信息
/// </summary>
private static readonly MethodInfo isNullOrWhiteSpaceMethodInfo;
/// <summary>
/// Guid到字符串
/// </summary>
private static readonly MethodInfo guidToStringMethodInfo;
/// <summary>
/// 静态构造方法
/// </summary>
static DbDataReaderExtensions()
{
var getValueMethod = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetValue), new Type[] { typeof(int) });
isDBNullMethodInfo = typeof(IDataRecord).GetMethod(nameof(IDataRecord.IsDBNull), new Type[] { typeof(int) });
isNullOrWhiteSpaceMethodInfo = typeof(string).GetMethod(nameof(string.IsNullOrWhiteSpace), new Type[] { typeof(string) });
guidToStringMethodInfo = typeof(Guid).GetMethod(nameof(Guid.ToString), new Type[] { typeof(Guid) });
getMethodInfoCache = new Dictionary<Type, MethodInfo>()
{
{ typeof(object),getValueMethod},
{ typeof(short),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt16), new Type[] { typeof(int) })},
{ typeof(ushort),getValueMethod},
{ typeof(int),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt32), new Type[] { typeof(int) })},
{ typeof(uint),getValueMethod},
{ typeof(long),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt64), new Type[] { typeof(int) })},
{ typeof(ulong),getValueMethod},
{ typeof(float),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetFloat), new Type[] { typeof(int) })},
{ typeof(double),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDouble), new Type[] { typeof(int) })},
{ typeof(decimal),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDecimal), new Type[] { typeof(int) })},
{ typeof(char),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetChar), new Type[] { typeof(int) })},
{ typeof(byte),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetByte), new Type[] { typeof(int) })},
{ typeof(sbyte),getValueMethod},
{ typeof(bool),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetBoolean),new Type[]{ typeof(int)})},
{ typeof(string),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetString),new Type[]{ typeof(int)})},
{ typeof(DateTime),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDateTime),new Type[]{ typeof(int)})},
{ typeof(TimeSpan),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetValue),new Type[]{ typeof(int)})},
{ typeof(Guid),typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetGuid),new Type[]{ typeof(int)})}
};
convertMethodInfos = new Dictionary<Type, ConvertInfo>()
{
{ typeof(short),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToInt16)
}
},
{ typeof(ushort),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToUInt16)
}
},
{ typeof(int),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToInt32)
}
},
{ typeof(uint),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToUInt32)
}
},
{ typeof(long),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToInt64)
}
},
{ typeof(ulong),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToUInt64)
}
},
{ typeof(float),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToSingle)
}
},
{ typeof(double),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToDouble)
}
},
{ typeof(decimal),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToDecimal)
} },
{ typeof(char),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToChar)
}
},
{ typeof(byte),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToByte)
}
},
{ typeof(sbyte),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToSByte)
}
},
{ typeof(bool),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToBoolean)
}
},
{ typeof(string),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToString)
}
},
{ typeof(DateTime),new ConvertInfo()
{
TargetType=typeof(Convert),
MethodName=nameof(Convert.ToDateTime)
}
},
{ typeof(Guid),new ConvertInfo()
{
TargetType=typeof(Guid),
MethodName=nameof(Guid.Parse)
}
}
};
}
/// <summary>
/// 快速设置值
/// </summary>
/// <param name="il">IL</param>
/// <param name="dbColumn">数据库列</param>
/// <param name="type">类型</param>
/// <param name="type">是否Json</param>
private static void FastSetValue(ILGenerator il, DbColumn dbColumn, Type type, bool isJson = false)
{
var getValueMethodInfo = getMethodInfoCache[dbColumn.DataType];
var underlyingType = Nullable.GetUnderlyingType(type);
var isNullable = false;
if (underlyingType != null)
{
isNullable = true;
}
else
{
underlyingType = type;
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, dbColumn.ColumnOrdinal.Value);
il.Emit(OpCodes.Callvirt, getValueMethodInfo);
if (isJson)
{
if (!getValueMethodInfo.ReturnType.Equals(typeof(string)))
{
throw new FastException($"数据库列{dbColumn.ColumnName}不是字符串类型不支持Json序列化.");
}
var ifLabel = il.DefineLabel();
var endIfLabel = il.DefineLabel();
il.Emit(OpCodes.Call, isNullOrWhiteSpaceMethodInfo);
il.Emit(OpCodes.Brtrue_S, ifLabel);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, dbColumn.ColumnOrdinal.Value);
il.Emit(OpCodes.Callvirt, getValueMethodInfo);
il.Emit(OpCodes.Ldnull);
var deserializeGenericMethodInfo = typeof(Json).GetMethod(nameof(Json.Deserialize));
var deserializeMethodInfo = deserializeGenericMethodInfo.MakeGenericMethod(type);
il.Emit(OpCodes.Call, deserializeMethodInfo);
il.Emit(OpCodes.Br_S, endIfLabel);
il.MarkLabel(ifLabel);
il.Emit(OpCodes.Ldnull);
il.MarkLabel(endIfLabel);
}
else
{
var returnType = getValueMethodInfo.ReturnType;
if (returnType.Equals(typeof(float)) || returnType.Equals(typeof(double)) || returnType.Equals(typeof(decimal)))
{
var v = il.DeclareLocal(returnType);
il.Emit(OpCodes.Stloc_S, v);
il.Emit(OpCodes.Ldloca_S, v);
il.Emit(OpCodes.Ldstr, "G0");
var converMethodInfo = returnType.GetMethod("ToString", new Type[] { typeof(string) });
il.Emit(OpCodes.Call, converMethodInfo);
returnType = typeof(string);
}
if (!underlyingType.Equals(returnType))//底层类型不等于值类型转换处理
{
if (dbColumn.DataType.Equals(typeof(Guid)) && underlyingType.Equals(typeof(string)))
{
il.Emit(OpCodes.Callvirt, guidToStringMethodInfo);//Guid转字符串
}
else
{
if (!convertMethodInfos.ContainsKey(underlyingType))
{
throw new NotSupportedException($"{nameof(underlyingType)}暂不支持转换.");
}
var converInfo = convertMethodInfos[underlyingType];
var converMethodInfo = converInfo.TargetType.GetMethod(converInfo.MethodName, new Type[] { returnType });
if (converMethodInfo.IsVirtual)
{
il.Emit(OpCodes.Callvirt, converMethodInfo);
}
else
{
il.Emit(OpCodes.Call, converMethodInfo);
}
}
}
if (isNullable)//可空类型转换
{
il.Emit(OpCodes.Call, underlyingType.GetToNullableMethodInfo());
}
}
}
/// <summary>
/// 快速设置值
/// </summary>
/// <param name="result">结果</param>
/// <param name="il">IL</param>
/// <param name="dbColumn">数据库列</param>
/// <param name="columnInfo">列信息</param>
private static void FastSetValue(LocalBuilder result, ILGenerator il, DbColumn dbColumn, ColumnInfo columnInfo)
{
il.Emit(OpCodes.Ldloc, result);
FastSetValue(il, dbColumn, columnInfo.MemberType, columnInfo.IsJson);
if (columnInfo.IsField)
{
il.Emit(OpCodes.Stfld, columnInfo.FieldInfo);
}
else
{
il.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.SetMethod);
}
}
/// <summary>
/// 初始化默认值
/// </summary>
/// <param name="il">IL</param>
/// <param name="type">类型</param>
private static void InitDeafultValue(ILGenerator il, Type type)
{
var v = il.DeclareLocal(type);
il.Emit(OpCodes.Ldloca_S, v);
il.Emit(OpCodes.Initobj, type);
il.Emit(OpCodes.Ldloc_S, v);
}
/// <summary>
/// 创建快速设置值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dbColumns">数据库列</param>
/// <returns></returns>
public static Func<IDataReader, T> CreateFastSetValue<T>(this ReadOnlyCollection<DbColumn> dbColumns)
{
var type = typeof(T);
var keys = dbColumns.Select(s =>
{
if (s.AllowDBNull == null)
{
return $"{s.ColumnName}_{s.DataTypeName}_True";
}
else
{
return $"{s.ColumnName}_{s.DataTypeName}_{s.AllowDBNull}";
}
});
var cacheKey = $"{nameof(CreateFastSetValue)}_{type.GUID}_{string.Join(",", keys)}";
return StaticCache<Func<IDataReader, T>>.GetOrAdd(cacheKey, () =>
{
var method = new DynamicMethod("FastEntity", type, new Type[] { typeof(IDataReader) }, type, true);
var il = method.GetILGenerator();
var result = il.DeclareLocal(type);
if (type.IsClass())
{
var entityInfo = type.GetEntityInfo();
if (entityInfo.IsAnonymousType)
{
//success
foreach (var dbColumn in dbColumns)
{
var columnInfo = entityInfo.ColumnInfos.FirstOrDefault(f => f.ColumnName == dbColumn.ColumnName);
if (columnInfo == null)
{
InitDeafultValue(il, entityInfo.ColumnInfos[dbColumn.ColumnOrdinal.Value].MemberType);
}
else
{
if (dbColumn.AllowDBNull == null || dbColumn.AllowDBNull.Value)
{
var ifLabel = il.DefineLabel();
var endIfLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, dbColumn.ColumnOrdinal.Value);
il.Emit(OpCodes.Callvirt, isDBNullMethodInfo);
il.Emit(OpCodes.Brtrue_S, ifLabel);
FastSetValue(il, dbColumn, columnInfo.MemberType, columnInfo.IsJson);
il.Emit(OpCodes.Br_S, endIfLabel);
il.MarkLabel(ifLabel);
InitDeafultValue(il, columnInfo.MemberType);
il.MarkLabel(endIfLabel);
}
else
{
FastSetValue(il, dbColumn, columnInfo.MemberType, columnInfo.IsJson);
}
}
}
var memberTypes = entityInfo.ColumnInfos.Select(s => s.MemberType).ToArray();
var constructorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, memberTypes);
il.Emit(OpCodes.Newobj, constructorInfo);
il.Emit(OpCodes.Stloc, result);
}
else
{
//success
var constructorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, Type.EmptyTypes);
il.Emit(OpCodes.Newobj, constructorInfo);
il.Emit(OpCodes.Stloc, result);
foreach (var dbColumn in dbColumns)
{
var columnInfo = entityInfo.ColumnInfos.FirstOrDefault(f => f.ColumnName == dbColumn.ColumnName);
if (columnInfo != null)
{
if (!getMethodInfoCache.ContainsKey(dbColumn.DataType))
{
throw new NotSupportedException($"数据类型:{dbColumn.DataType}暂不支持绑定.");
}
if (dbColumn.AllowDBNull == null || dbColumn.AllowDBNull.Value)
{
var endIfLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, dbColumn.ColumnOrdinal.Value);
il.Emit(OpCodes.Callvirt, isDBNullMethodInfo);
il.Emit(OpCodes.Brtrue, endIfLabel);
FastSetValue(result, il, dbColumn, columnInfo);
il.MarkLabel(endIfLabel);
}
else
{
FastSetValue(result, il, dbColumn, columnInfo);
}
}
}
}
il.Emit(OpCodes.Ldloc, result);
il.Emit(OpCodes.Ret);
}
else
{
//success
if (dbColumns[0].AllowDBNull == null || dbColumns[0].AllowDBNull.Value)
{
var endIfLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, dbColumns[0].ColumnOrdinal.Value);
il.Emit(OpCodes.Callvirt, isDBNullMethodInfo);
il.Emit(OpCodes.Brtrue, endIfLabel);
FastSetValue(il, dbColumns[0], typeof(T));
il.Emit(OpCodes.Stloc, result);
il.MarkLabel(endIfLabel);
}
else
{
FastSetValue(il, dbColumns[0], typeof(T));
il.Emit(OpCodes.Stloc, result);
}
il.Emit(OpCodes.Ldloc, result);
il.Emit(OpCodes.Ret);
}
return method.CreateDelegate<Func<IDataReader, T>>();
});
}
/// <summary>
/// 最终处理
/// </summary>
/// <param name="reader">阅读器</param>
/// <returns></returns>
private static void FinalProcessing(this DbDataReader reader)
{
if (!reader.NextResult())
{
reader.Close();
}
}
/// <summary>
/// 最终处理异步
/// </summary>
/// <param name="reader">阅读器</param>
/// <returns></returns>
private static async Task FinalProcessingAsync(this DbDataReader reader)
{
if (!await reader.NextResultAsync())
{
await reader.CloseAsync();
}
}
/// <summary>
/// 第一构建
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static T FirstBuild<T>(this DbDataReader dataReader)
{
var reader = dataReader;
var dbColumns = reader.GetColumnSchema();
T t = default;
if (reader.Read())
{
var func = dbColumns.CreateFastSetValue<T>();
t = func.Invoke(reader);
}
reader.FinalProcessing();
return t;
}
/// <summary>
/// 第一构建异步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static async Task<T> FirstBuildAsync<T>(this Task<DbDataReader> dataReader)
{
var reader = await dataReader;
var dbColumns = await reader.GetColumnSchemaAsync();
T t = default;
if (await reader.ReadAsync())
{
var func = dbColumns.CreateFastSetValue<T>();
t = func.Invoke(reader);
}
await reader.FinalProcessingAsync();
return t;
}
/// <summary>
/// 列表构建
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static List<T> ListBuild<T>(this DbDataReader dataReader)
{
var reader = dataReader;
var dbColumns = reader.GetColumnSchema();
var list = new List<T>();
var func = dbColumns.CreateFastSetValue<T>();
while (reader.Read())
{
list.Add(func.Invoke(reader));
}
reader.FinalProcessing();
return list;
}
/// <summary>
/// 列表构建异步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static async Task<List<T>> ListBuildAsync<T>(this Task<DbDataReader> dataReader)
{
var reader = await dataReader;
var dbColumns = await reader.GetColumnSchemaAsync();
var list = new List<T>();
var func = dbColumns.CreateFastSetValue<T>();
while (await reader.ReadAsync())
{
list.Add(func.Invoke(reader));
}
await reader.FinalProcessingAsync();
return list;
}
/// <summary>
/// 字典构建
/// </summary>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static Dictionary<string, object> DictionaryBuild(this DbDataReader dataReader)
{
var reader = dataReader;
var data = new Dictionary<string, object>();
var dbColumns = reader.GetColumnSchema();
if (dbColumns.Count > 0 && reader.Read())
{
data = new Dictionary<string, object>();
foreach (var c in dbColumns)
{
data.Add(c.ColumnName, reader.IsDBNull(c.ColumnOrdinal.Value) ? null : reader.GetValue(c.ColumnOrdinal.Value));
}
}
reader.FinalProcessing();
return data;
}
/// <summary>
/// 字典构建异步
/// </summary>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static async Task<Dictionary<string, object>> DictionaryBuildAsync(this Task<DbDataReader> dataReader)
{
var reader = await dataReader;
var data = new Dictionary<string, object>();
var dbColumns = await reader.GetColumnSchemaAsync();
if (dbColumns.Count > 0 && await reader.ReadAsync())
{
data = new Dictionary<string, object>();
foreach (var c in dbColumns)
{
data.Add(c.ColumnName, reader.IsDBNull(c.ColumnOrdinal.Value) ? null : reader.GetValue(c.ColumnOrdinal.Value));
}
}
await reader.FinalProcessingAsync();
return data;
}
/// <summary>
/// 字典列表构建
/// </summary>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static List<Dictionary<string, object>> DictionaryListBuild(this DbDataReader dataReader)
{
var reader = dataReader;
var data = new List<Dictionary<string, object>>();
var dbColumns = reader.GetColumnSchema();
if (dbColumns.Count > 0)
{
while (reader.Read())
{
var keyValues = new Dictionary<string, object>();
foreach (var c in dbColumns)
{
keyValues.Add(c.ColumnName, reader.IsDBNull(c.ColumnOrdinal.Value) ? null : reader.GetValue(c.ColumnOrdinal.Value));
}
data.Add(keyValues);
}
}
reader.FinalProcessing();
return data;
}
/// <summary>
/// 字典列表构建异步
/// </summary>
/// <param name="dataReader">数据读取</param>
/// <returns></returns>
public static async Task<List<Dictionary<string, object>>> DictionaryListBuildAsync(this Task<DbDataReader> dataReader)
{
var reader = await dataReader;
var data = new List<Dictionary<string, object>>();
var dbColumns = await reader.GetColumnSchemaAsync();
if (dbColumns.Count > 0)
{
while (await reader.ReadAsync())
{
var keyValues = new Dictionary<string, object>();
foreach (var c in dbColumns)
{
keyValues.Add(c.ColumnName, reader.IsDBNull(c.ColumnOrdinal.Value) ? null : reader.GetValue(c.ColumnOrdinal.Value));
}
data.Add(keyValues);
}
}
await reader.FinalProcessingAsync();
return data;
}
}
}