首页 > 数据库技术 > 详细

开源映射器(一千行左右)SqlCommon,性能接近ADO.NET

时间:2019-10-01 20:03:17      阅读:114      评论:0      收藏:0      [点我收藏+]

一、核心组件-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);
                    }
                }
            }
        }

    }

}
SqlMapper

二、核心组件-实体映射器

技术分享图片
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&lt;tstring, object&gt;
        /// </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>;
            }

        }
    }
}
TypeConvert

三、核心组件-类型转换策略

技术分享图片
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
    }
}
TypeMapper

使用方法同基本同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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!