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数据,按指定字段对数据进行排序,从而在页面上进 ...
随机推荐
- 基于C# 开发的SOL SERVER 操作数据库类(SQLHelp)
说明:以下是我近两年年来开发中最常用的C#操作sql server数据库访问类,对初学者非常有用,容易扩展,支持多库操作,多研究研究,有什么问题欢迎留言 当前环境为 C# .NET CORE 3.0 ...
- 解决 echarts柱状图x轴数据隔一个显示
echarts柱状图x轴数据隔一个显示 在显示一个柱状图的时候,x轴的数据是隔一个显示的,但是hover的时候却能显示出当前轴x轴的名称,如下图: 那就只能说明这个轴的名称太长了,所以导致它默认就 ...
- docker 安装redis 6.0.8哨兵集群(一主两从三哨兵)
准备三台主机并且安装了docker 192.168.31.132 192.168.31.134 192.168.31.144 linux 版redis6.0.8 下载 下载地址:https://dow ...
- 使用C#编写.NET分析器(三)
译者注 这是在Datadog公司任职的Kevin Gosse大佬使用C#编写.NET分析器的系列文章之一,在国内只有很少很少的人了解和研究.NET分析器,它常被用于APM(应用性能诊断).IDE.诊断 ...
- 分享一个Java功能小案例(代码已开源哦)
工程合集 工程列表 地址预览 B站 抖音
- Android 架构模式如何选择
作者:vivo 互联网客户端团队-Xu Jie Android架构模式飞速演进,目前已经有MVC.MVP.MVVM.MVI.到底哪一个才是自己业务场景最需要的,不深入理解的话是无法进行选择的.这篇文章 ...
- Codeforces Round 882 (Div. 2)
Codeforces Round 882 (Div. 2) A.The Man who became a God 题目大意 给定一个数组 \({x_1,x_2,⋯,x_n}\) 和一个整数 \(k\) ...
- Cesium SuperMap问题调研汇总
https://segmentfault.com/a/1190000040577369?sort=newest
- 使用lame转wav为mp3
使用lame转wav为mp3 由于服务器之前都是直接存储wav格式的录音文件,存储空间总是不够用.网上搜索了一下,可以使用lame这个开源工具,将wav转成MP3 格式,还可以将mp3文件转回wav格 ...
- centos7安装influxdb2
前言 InfluxDB是一个由InfluxData开发的开源时序型数据库,专注于海量时序数据的高性能读.高性能写.高效存储与实时分析等,广泛应用于DevOps监控.IoT监控.实时分析等场景. 服务器 ...