Emit 实体绑定源码开源,支持类以及匿名类绑定(原创)
动态实体绑定 主要有以下两种
1、表达式树构建委托
2、Emit构建委托
根据我的经验 Emit 代码量可以更少可以很好实现代码复用
Emit实践开源项目地址跳转 https://www.cnblogs.com/China-Mr-zhong/p/17514567.html 查看
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;
}
}
}
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;
}
}
}
Emit 实体绑定源码开源,支持类以及匿名类绑定(原创)的更多相关文章
- 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端
[转]TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端).UDP客户端 目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP ...
- 日志组件Log2Net的介绍和使用(附源码开源地址)
Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...
- Netty 源码 Channel(二)核心类
Netty 源码 Channel(二)核心类 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一.Channel 类图 二. ...
- Netty 源码 Channel(二)主要类
Netty 源码 Channel(二)主要类 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一.Channel 类图 二. ...
- JUC源码分析-集合篇:并发类容器介绍
JUC源码分析-集合篇:并发类容器介绍 同步类容器是 线程安全 的,如 Vector.HashTable 等容器的同步功能都是由 Collections.synchronizedMap 等工厂方法去创 ...
- Jsoup解析网页源码时常用的Element(s)类
Jsoup解析网页源码时常用的Element(s)类 一.简介 该类是Node的直接子类,同样实现了可克隆接口.类声明:public class Element extends Node 它表示由一个 ...
- C# 网络斗地主源码开源
C# 网络斗地主源码开源多线程 讨论交流及 下载地址 可以发送聊天消息
- android:“新版飞机大战”源码开源啦!
今天10.24,为了纪念程序猿的节日,把之前写过的一个"飞机大战"的一个源码开源了. 源码地址:https://github.com/nuptboyzhb/newplanegame ...
- 1、Spark 2.1 源码编译支持CDH
目前CDH支持的spark版本都是1.x, 如果想要使用spark 2x的版本, 只能编译spark源码生成支持CDH的版本. 一.准备工作 找一台Linux主机, 由于spark源码编译会下载很多的 ...
- THINKPHP_(8)_修改TP源码,支持基于多层关联的任一字段进行排序
之前博文 前述博文THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序,其解决的主要问题是,对于查询出的think\collection数据,按指定字段对数据进行排序,从而在页面上进 ...
随机推荐
- 数仓性能调优:大宽表关联MERGE性能优化
摘要:本文主要为大家讲解在数仓性能调优过程中,关于大宽表关联MERGE性能优化过程. 本文分享自华为云社区<GaussDB(DWS)性能调优:大宽表关联MERGE性能优化>,作者:譡里个檔 ...
- [ESP] 使用Ayla API Reference配网和连Ayla云
示例用的文档及链接 US Dev Dashboard(查看oem-id和oem-key) https://dashboard-dev.aylanetworks.com/ Ayla API Refere ...
- Java的readBytes是怎么实现的?
1.前言 众所周知,Java是一门跨平台语言,针对不同的操作系统有不同的实现.本文从一个非常简单的api调用来看看Java具体是怎么做的. 2.源码分析 从FileInputStream.java中看 ...
- 关于No changes detected
查看app在settings.py文件夹中是否有注册.
- sqlmap指定参数注入
在参数前面加星号
- [Python]数组基础
在python中,一般使用列表表示数组.例如: 一维数组 arr1 = [1,2,3,4] 二维数组 arr2 = [[1,2,3,4],[5,6,7,8]] 数组的常用操作 追加 利用append( ...
- Unity的AssetPostprocessor之Model之动画:深入解析与实用案例 3
Unity AssetPostprocessor的Model的动画相关的函数修改实际应用 在Unity中,AssetPostprocessor是一个非常有用的工具,它可以在导入资源时自动执行一些操作. ...
- 微服务集成seata完成分布式事务,解决数据不一致问题
细心的盆友可能已经发现了,我们的跨行转账并没有保证数据一致性,比如小明扣除了100,但是因为各种问题小红在添加100金额的时候遇到了异常,这个时候数据就出现不一致性 我们可以选择seata来进行分布式 ...
- 三维模型OSGB格式轻量化压缩必要性分析
三维模型OSGB格式轻量化压缩必要性分析 三维模型是计算机图形学和视觉效果等领域的重要应用之一.然而,由于三维模型通常包含大量的几何信息.纹理信息和其他元素,导致其占用的存储空间和计算资源非常巨大.为 ...
- 我的新书《Flink大数据分析实战》出版啦