一、核心组件-sql映射器
using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.RegularExpressions; using System.Collections; using System.Data.Common; using System.Threading; namespace SqlCommon { /// <summary> /// Extended connection /// </summary> public static class SqlMapper { /// <summary> /// Type mapper /// </summary> public static ITypeMapper TypeMapper = new TypeMapper(); /// <summary> /// Does name matching ignore underscores /// </summary> public static bool MatchNamesWithUnderscores { get; set; } /// <summary> /// Executes a query, returning the data typed as T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="commandTimeout"> Timeout</param> /// <param name="commandType"></param> /// <returns></returns> public static IEnumerable<T> ExecuteQuery<T>(this IDbConnection connection, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) connection.Open(); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); using (var reader = cmd.ExecuteReader()) { var handler = TypeConvert.GetSerializer<T>(reader); while (reader.Read()) { yield return handler(reader); } } } } /// <summary> /// Execute parameterized SQL /// </summary> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="commandTimeout"></param> /// <param name="commandType"></param> /// <returns></returns> public static int ExecuteNonQuery(this IDbConnection connection, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) connection.Open(); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); return cmd.ExecuteNonQuery(); } } /// <summary> /// Executes a query, returning the data typed as T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="cancelToken"></param> /// <param name="commandTimeout"> Timeout</param> /// <param name="commandType"> Type</param> /// <returns></returns> public async static Task<IEnumerable<T>> ExecuteQueryAsync<T>(this DbConnection connection, string sql, object param = null, IDbTransaction transaction = null, CancellationToken? cancelToken = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) await (cancelToken == null ? connection.OpenAsync() : connection.OpenAsync(cancelToken.Value)); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); using (var reader = await (cancelToken == null ? cmd.ExecuteReaderAsync() : cmd.ExecuteReaderAsync(cancelToken.Value))) { var list = new List<T>(); var handler = TypeConvert.GetSerializer<T>(reader); while (await reader.ReadAsync()) { list.Add(handler(reader)); } return list; } } } /// <summary> /// Execute a command asynchronously using Task. /// </summary> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="cancelToken"></param> /// <param name="commandTimeout"></param> /// <param name="commandType"></param> /// <returns></returns> public async static Task<int> ExecuteNonQueryAsync(this DbConnection connection, string sql, object param = null, IDbTransaction transaction = null, CancellationToken? cancelToken = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) await (cancelToken == null ? connection.OpenAsync() : connection.OpenAsync(cancelToken.Value)); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); return await (cancelToken == null ? cmd.ExecuteNonQueryAsync() : cmd.ExecuteNonQueryAsync(cancelToken.Value)); } } /// <summary> /// Execute parameterized SQL that selects a single value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="commandTimeout"></param> /// <param name="commandType"></param> /// <returns></returns> public static T ExecuteScalar<T>(this IDbConnection connection, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) connection.Open(); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); var result = cmd.ExecuteScalar(); if (result is DBNull) { return default; } return (T)Convert.ChangeType(result, typeof(T)); } } /// <summary> /// Execute parameterized SQL that selects a single value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="param"></param> /// <param name="transaction"></param> /// <param name="cancelToken"></param> /// <param name="commandTimeout"></param> /// <param name="commandType"></param> /// <returns></returns> public async static Task<T> ExecuteScalarAsync<T>(this DbConnection connection, string sql, object param = null, IDbTransaction transaction = null, CancellationToken? cancelToken = null, int? commandTimeout = null, CommandType? commandType = null) { if (connection.State == ConnectionState.Closed) await (cancelToken == null ? connection.OpenAsync() : connection.OpenAsync(cancelToken.Value)); using (var cmd = connection.CreateCommand()) { Initialize(cmd, transaction, sql, param, commandTimeout, commandType); var result = await (cancelToken == null ? cmd.ExecuteScalarAsync() : cmd.ExecuteScalarAsync(cancelToken.Value)); if (result is DBNull) { return default; } return (T)Convert.ChangeType(result, typeof(T)); } } private static void Initialize(IDbCommand cmd, IDbTransaction transaction, string sql, object param, int? commandTimeout = null, CommandType? commandType = null) { cmd.Transaction = transaction; cmd.CommandText = sql; if (commandTimeout.HasValue) { cmd.CommandTimeout = commandTimeout.Value; } if (commandType.HasValue) { cmd.CommandType = commandType.Value; } if (param != null) { var handler = TypeConvert.Deserializer(param); var values = handler(param); foreach (var item in values) { var pattern = $@"in\s+([\@,\:,\?]?{item.Key})"; if (Regex.IsMatch(cmd.CommandText, pattern)) { var name = Regex.Match(cmd.CommandText, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline).Groups[1].Value; var list = new List<object>(); if (item.Value is IEnumerable<object> || item.Value is Array) { list = (item.Value as IEnumerable).Cast<object>().Where(a => a != null && a != DBNull.Value).ToList(); } else { list.Add(item.Value); } if (list.Count() > 0) { cmd.CommandText = Regex.Replace(cmd.CommandText, name, $"({string.Join(",", list.Select(s => $"{name}{list.IndexOf(s)}"))})"); foreach (var iitem in list) { var parameter = cmd.CreateParameter(); parameter.ParameterName = $"{item.Key}{list.IndexOf(iitem)}"; parameter.Value = iitem; cmd.Parameters.Add(parameter); } } else { cmd.CommandText = Regex.Replace(cmd.CommandText, name, $"(SELECT 1 WHERE 1 = 0)"); } } else { var parameter = cmd.CreateParameter(); parameter.ParameterName = item.Key; parameter.Value = item.Value; cmd.Parameters.Add(parameter); } } } } } }
二、核心组件-实体映射器
using System; using System.Collections.Generic; using System.Linq; using System.Data; using System.Text; using System.Reflection; using System.Reflection.Emit; using System.Threading.Tasks; namespace SqlCommon { /// <summary> /// DbColumn Information /// </summary> public class DbDataInfo { public string TypeName { get; set; } public Type DataType { get; set; } public string DataName { get; set; } public int Ordinal { get; set; } public DbDataInfo(int ordinal, string typeName, Type dataType, string dataName) { Ordinal = ordinal; TypeName = typeName; DataType = dataType; DataName = dataName; } } /// <summary> /// Type Convert /// </summary> public class TypeConvert { private static Dictionary<SerializerKey, object> _serializers = new Dictionary<SerializerKey, object>(); private static Dictionary<Type, Func<object, Dictionary<string, object>>> _deserializers = new Dictionary<Type, Func<object, Dictionary<string, object>>>(); private struct SerializerKey : IEquatable<SerializerKey> { private string[] Names { get; set; } private Type Type { get; set; } public override bool Equals(object obj) { return obj is SerializerKey && Equals((SerializerKey)obj); } public bool Equals(SerializerKey other) { if (Type != other.Type) { return false; } else if (Names.Length != other.Names.Length) { return false; } else { for (int i = 0; i < Names.Length; i++) { if (Names[i] != other.Names[i]) { return false; } } return true; } } public override int GetHashCode() { return Type.GetHashCode(); } public SerializerKey(Type type, string[] names) { Type = type; Names = names; } } /// <summary> /// IDataRecord Converted to T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="mapper">Type Mapper</param> /// <param name="record">IDataRecord</param> /// <returns></returns> public static Func<IDataRecord, T> GetSerializer<T>(ITypeMapper mapper, IDataRecord record) { string[] names = new string[record.FieldCount]; for (int i = 0; i < record.FieldCount; i++) { names[i] = record.GetName(i); } var key = new SerializerKey(typeof(T), names); _serializers.TryGetValue(key, out object handler); if (handler == null) { lock (_serializers) { handler = CreateTypeSerializerHandler<T>(mapper, record); if (!_serializers.ContainsKey(key)) { _serializers.Add(key, handler); } } } return handler as Func<IDataRecord, T>; } /// <summary> /// IDataRecord Converted to T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="record"></param> /// <returns></returns> public static Func<IDataRecord, T> GetSerializer<T>(IDataRecord record) { return GetSerializer<T>(new TypeMapper(), record); } /// <summary> /// Object To Dictionary<tstring, object> /// </summary> /// <param name="value"></param> /// <returns></returns> public static Func<object, Dictionary<string, object>> Deserializer(object value) { Func<object, Dictionary<string, object>> handler = null; if (value is Dictionary<string, object>) { return (object param) => param as Dictionary<string, object>; } var type = value.GetType(); _deserializers.TryGetValue(type, out handler); if (handler == null) { lock (_deserializers) { handler = CreateTypeDeserializeHandler(type) as Func<object, Dictionary<string, object>>; if (!_deserializers.ContainsKey(type)) { _deserializers.Add(type, handler); } } } return handler; } private static Func<object, Dictionary<string, object>> CreateTypeDeserializeHandler(Type type) { var properties = type.GetProperties(); var dynamicMethod = new DynamicMethod($"Serializer{type.Name}", typeof(Dictionary<string, object>), new Type[] { typeof(object) }, type, true); var generator = dynamicMethod.GetILGenerator(); LocalBuilder entityLocal = generator.DeclareLocal(typeof(Dictionary<string, object>)); generator.Emit(OpCodes.Newobj, typeof(Dictionary<string, object>).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, entityLocal); foreach (var item in properties) { generator.Emit(OpCodes.Ldloc, entityLocal); generator.Emit(OpCodes.Ldstr, item.Name); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, item.GetGetMethod()); if (item.PropertyType.IsValueType) { generator.Emit(OpCodes.Box, item.PropertyType); } generator.Emit(OpCodes.Callvirt, typeof(Dictionary<string, object>).GetMethod(nameof(Dictionary<string, object>.Add), new Type[] { typeof(string), typeof(object) })); } generator.Emit(OpCodes.Ldloc, entityLocal); generator.Emit(OpCodes.Ret); return dynamicMethod.CreateDelegate(typeof(Func<object, Dictionary<string, object>>)) as Func<object, Dictionary<string, object>>; } private static Func<IDataRecord, T> CreateTypeSerializerHandler<T>(ITypeMapper mapper, IDataRecord record) { var type = typeof(T); var dynamicMethod = new DynamicMethod($"{type.Name}Deserializer{Guid.NewGuid().ToString("N")}", type, new Type[] { typeof(IDataRecord) }, type, true); var generator = dynamicMethod.GetILGenerator(); LocalBuilder local = generator.DeclareLocal(type); var dataInfos = new DbDataInfo[record.FieldCount]; for (int i = 0; i < record.FieldCount; i++) { var dataname = record.GetName(i); var datatype = record.GetFieldType(i); var typename = record.GetDataTypeName(i); dataInfos[i] = new DbDataInfo(i, typename, datatype, dataname); } if (dataInfos.Length == 1) { var convertMethod = mapper.FindConvertMethod(type); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, 0); if (convertMethod.IsVirtual) generator.Emit(OpCodes.Callvirt, convertMethod); else generator.Emit(OpCodes.Call, convertMethod); generator.Emit(OpCodes.Stloc, local); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return dynamicMethod.CreateDelegate(typeof(Func<IDataRecord, T>)) as Func<IDataRecord, T>; } var constructor = mapper.FindConstructor(type); if (constructor.GetParameters().Length > 0) { var parameters = constructor.GetParameters(); var locals = new LocalBuilder[parameters.Length]; for (int i = 0; i < locals.Length; i++) { locals[i] = generator.DeclareLocal(parameters[i].ParameterType); } for (int i = 0; i < locals.Length; i++) { var item = mapper.FindConstructorParameter(dataInfos, parameters[i]); if (item == null) { continue; } var convertMethod = mapper.FindConvertMethod(parameters[i].ParameterType); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, item.Ordinal); if (convertMethod.IsVirtual) generator.Emit(OpCodes.Callvirt, convertMethod); else generator.Emit(OpCodes.Call, convertMethod); generator.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < locals.Length; i++) { generator.Emit(OpCodes.Ldloc, locals[i]); } generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Stloc, local); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return dynamicMethod.CreateDelegate(typeof(Func<IDataRecord, T>)) as Func<IDataRecord, T>; } else { var properties = type.GetProperties(); generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Stloc, local); foreach (var item in dataInfos) { var property = mapper.FindMember(properties, item) as PropertyInfo; if (property == null) { continue; } var convertMethod = mapper.FindConvertMethod(property.PropertyType); if (convertMethod == null) { continue; } int i = record.GetOrdinal(item.DataName); generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); if (convertMethod.IsVirtual) generator.Emit(OpCodes.Callvirt, convertMethod); else generator.Emit(OpCodes.Call, convertMethod); generator.Emit(OpCodes.Callvirt, property.GetSetMethod()); } generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ret); return dynamicMethod.CreateDelegate(typeof(Func<IDataRecord, T>)) as Func<IDataRecord, T>; } } } }
三、核心组件-类型转换策略
using System; using System.Data; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace SqlCommon { /// <summary> /// TypeMapper Interface /// </summary> public interface ITypeMapper { MemberInfo FindMember(MemberInfo[] properties, DbDataInfo dataInfo); MethodInfo FindConvertMethod(Type csharpType); DbDataInfo FindConstructorParameter(DbDataInfo[] dataInfos, ParameterInfo parameterInfo); ConstructorInfo FindConstructor(Type csharpType); } /// <summary> /// Default TypeMapper /// </summary> public class TypeMapper : ITypeMapper { /// <summary> /// Find parametric constructors. /// If there is no default constructor, the constructor with the most parameters is returned. /// </summary> /// <param name="csharpType"></param> /// <returns></returns> public ConstructorInfo FindConstructor(Type csharpType) { var constructor = csharpType.GetConstructor(Type.EmptyTypes); if (constructor == null) { var constructors = csharpType.GetConstructors(); constructor = constructors.Where(a => a.GetParameters().Length == constructors.Max(s => s.GetParameters().Length)).FirstOrDefault(); } return constructor; } /// <summary> /// Returns field information based on parameter information /// </summary> /// <param name="dataInfos"></param> /// <param name="parameterInfo"></param> /// <returns></returns> public DbDataInfo FindConstructorParameter(DbDataInfo[] dataInfos, ParameterInfo parameterInfo) { foreach (var item in dataInfos) { if (item.DataName.Equals(parameterInfo.Name, StringComparison.OrdinalIgnoreCase)) { return item; } else if (SqlMapper.MatchNamesWithUnderscores && item.DataName.Replace("_", "").Equals(parameterInfo.Name, StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } /// <summary> /// Returns attribute information based on field information /// </summary> /// <param name="properties"></param> /// <param name="dataInfo"></param> /// <returns></returns> public MemberInfo FindMember(MemberInfo[] properties, DbDataInfo dataInfo) { foreach (var item in properties) { if (item.Name.Equals(dataInfo.DataName, StringComparison.OrdinalIgnoreCase)) { return item; } else if (SqlMapper.MatchNamesWithUnderscores && item.Name.Equals(dataInfo.DataName.Replace("_", ""), StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } /// <summary> /// Return type conversion function. /// </summary> /// <param name="csharpType"></param> /// <returns></returns> public MethodInfo FindConvertMethod(Type csharpType) { if (csharpType == typeof(byte) || Nullable.GetUnderlyingType(csharpType) == typeof(byte)) { return csharpType == typeof(byte) ? DataConvertMethod.ToByteMethod : DataConvertMethod.ToByteNullableMethod; } if (csharpType == typeof(short) || Nullable.GetUnderlyingType(csharpType) == typeof(short)) { return csharpType == typeof(short) ? DataConvertMethod.ToIn16Method : DataConvertMethod.ToIn16NullableMethod; } if (csharpType == typeof(int) || Nullable.GetUnderlyingType(csharpType) == typeof(int)) { return csharpType == typeof(int) ? DataConvertMethod.ToIn32Method : DataConvertMethod.ToIn32NullableMethod; } if (csharpType == typeof(long) || Nullable.GetUnderlyingType(csharpType) == typeof(long)) { return csharpType == typeof(long) ? DataConvertMethod.ToIn64Method : DataConvertMethod.ToIn64NullableMethod; } if (csharpType == typeof(float) || Nullable.GetUnderlyingType(csharpType) == typeof(float)) { return csharpType == typeof(float) ? DataConvertMethod.ToFloatMethod : DataConvertMethod.ToFloatNullableMethod; } if (csharpType == typeof(double) || Nullable.GetUnderlyingType(csharpType) == typeof(double)) { return csharpType == typeof(double) ? DataConvertMethod.ToDoubleMethod : DataConvertMethod.ToDoubleNullableMethod; } if (csharpType == typeof(decimal) || Nullable.GetUnderlyingType(csharpType) == typeof(decimal)) { return csharpType == typeof(decimal) ? DataConvertMethod.ToDecimalMethod : DataConvertMethod.ToDecimalNullableMethod; } if (csharpType == typeof(bool) || Nullable.GetUnderlyingType(csharpType) == typeof(bool)) { return csharpType == typeof(bool) ? DataConvertMethod.ToBooleanMethod : DataConvertMethod.ToBooleanNullableMethod; } if (csharpType == typeof(char) || Nullable.GetUnderlyingType(csharpType) == typeof(char)) { return csharpType == typeof(char) ? DataConvertMethod.ToCharMethod : DataConvertMethod.ToCharNullableMethod; } if (csharpType == typeof(string)) { return DataConvertMethod.ToStringMethod; } if (csharpType == typeof(DateTime) || Nullable.GetUnderlyingType(csharpType) == typeof(DateTime)) { return csharpType == typeof(DateTime) ? DataConvertMethod.ToDateTimeMethod : DataConvertMethod.ToDateTimeNullableMethod; } if (csharpType.IsEnum || Nullable.GetUnderlyingType(csharpType).IsEnum) { return csharpType.IsEnum ? DataConvertMethod.ToEnumMethod.MakeGenericMethod(Nullable.GetUnderlyingType(csharpType)) : DataConvertMethod.ToEnumNullableMethod.MakeGenericMethod(Nullable.GetUnderlyingType(csharpType)); } if (csharpType == typeof(Guid) || Nullable.GetUnderlyingType(csharpType) == typeof(Guid)) { return csharpType == typeof(Guid) ? DataConvertMethod.ToGuidMethod : DataConvertMethod.ToGuidNullableMethod; } return null; } } public static class DataConvertMethod { #region Method Field public static MethodInfo ToByteMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToByte)); public static MethodInfo ToIn16Method = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt16)); public static MethodInfo ToIn32Method = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt32)); public static MethodInfo ToIn64Method = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt64)); public static MethodInfo ToFloatMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToFloat)); public static MethodInfo ToDoubleMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDouble)); public static MethodInfo ToDecimalMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDecimal)); public static MethodInfo ToBooleanMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToBoolean)); public static MethodInfo ToCharMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToChar)); public static MethodInfo ToStringMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToString)); public static MethodInfo ToDateTimeMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDateTime)); public static MethodInfo ToEnumMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToEnum)); public static MethodInfo ToGuidMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToGuid)); #endregion #region NullableMethod Field public static MethodInfo ToByteNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt16Nullable)); public static MethodInfo ToIn16NullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt16Nullable)); public static MethodInfo ToIn32NullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt32Nullable)); public static MethodInfo ToIn64NullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToInt64Nullable)); public static MethodInfo ToFloatNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToFloatNullable)); public static MethodInfo ToDoubleNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDoubleNullable)); public static MethodInfo ToBooleanNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToBooleanNullable)); public static MethodInfo ToDecimalNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDecimalNullable)); public static MethodInfo ToCharNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToCharNullable)); public static MethodInfo ToDateTimeNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToDateTimeNullable)); public static MethodInfo ToEnumNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToEnumNullable)); public static MethodInfo ToGuidNullableMethod = typeof(DataConvertMethod).GetMethod(nameof(DataConvertMethod.ConvertToGuidNullable)); #endregion #region Define Convert public static byte ConvertToByte(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetByte(i); return result; } public static short ConvertToInt16(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt16(i); return result; } public static int ConvertToInt32(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt32(i); return result; } public static long ConvertToInt64(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt64(i); return result; } public static float ConvertToFloat(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetFloat(i); return result; } public static double ConvertToDouble(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDouble(i); return result; } public static bool ConvertToBoolean(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetBoolean(i); return result; } public static decimal ConvertToDecimal(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDecimal(i); return result; } public static char ConvertToChar(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetChar(i); return result; } public static string ConvertToString(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetString(i); return result; } public static DateTime ConvertToDateTime(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDateTime(i); return result; } public static T ConvertToEnum<T>(this IDataRecord dr, int i) where T : struct { if (dr.IsDBNull(i)) { return default; } var value = dr.GetInt32(i); if (Enum.TryParse(value.ToString(), out T result)) return result; return default; } public static Guid ConvertToGuid(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetGuid(i); return result; } #endregion #region Define Nullable Convert public static byte? ConvertToByteNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetByte(i); return result; } public static short? ConvertToInt16Nullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt16(i); return result; } public static int? ConvertToInt32Nullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt32(i); return result; } public static long? ConvertToInt64Nullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetInt64(i); return result; } public static float? ConvertToFloatNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetFloat(i); return result; } public static double? ConvertToDoubleNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDouble(i); return result; } public static bool? ConvertToBooleanNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetBoolean(i); return result; } public static decimal? ConvertToDecimalNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDecimal(i); return result; } public static char? ConvertToCharNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetChar(i); return result; } public static DateTime? ConvertToDateTimeNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetDateTime(i); return result; } public static T? ConvertToEnumNullable<T>(this IDataRecord dr, int i) where T : struct { if (dr.IsDBNull(i)) { return default; } var value = dr.GetInt32(i); if (Enum.TryParse(value.ToString(), out T result)) return result; return default; } public static Guid? ConvertToGuidNullable(this IDataRecord dr, int i) { if (dr.IsDBNull(i)) { return default; } var result = dr.GetGuid(i); return result; } #endregion } }
使用方法同基本同Dapper
public void Test() {
//执行查询,目前参数只支持Dictionary<string,object>()和所有的class类型 var list = connection.ExecuteQuery<Student>("select id as id,nick_name as NickName from student where id = @id",new {Id=1});
//执行命令
var row = connection.Execute("insert into student(nick_name) values (@Name)",new { NickName = "sqlcommon" }); }
Github:https://github.com/1448376744/SqlCommon
免责申明
开源映射器(一千行左右)SqlCommon,性能接近ADO.NET
原文:https://www.cnblogs.com/chaeyeon/p/11615863.html