• 关于Dapper的使用笔记3


    1、默认的类型映射,直接以实体属性(或字段)映射到SQL中字段,(名称可以忽略大小写)

    2、如果字段带下划线的,设置Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 即可。

    3、正因为有这个DefaultTypeMap默认的映射策略,所以,一般情况下,可以直接通过SQL查询,生成实体List.

    4、Dapper还是以数据库为中心的思考问题模式,不同于Entity framework和nhibernate,提倡以实体到DB的思考问题方式。

    5、Dapper在处理实体关联方面算是硬伤了,只能程序员自已根据DTO的模型去自已动手组装了。

    附上代码

        /// <summary>
        /// 表示Dapper默认的类型映射策略
        /// Represents default type mapping strategy used by Dapper
        /// </summary>
        sealed partial class DefaultTypeMap : SqlMapper.ITypeMap
        {
            /// <summary>
            /// 要映射的实体,所有的字段
            /// </summary>
            private readonly List<FieldInfo> _fields;
    
            /// <summary>
            /// 要映射的实体,所有的属性
            /// </summary>
            private readonly List<PropertyInfo> _properties;
    
            /// <summary>
            /// 要映射的实体类型
            /// </summary>
            private readonly Type _type;
    
            /// <summary>
            /// 构造函数,创建缺省的类型映射策略
            /// Creates default type map
            /// </summary>
            /// <param name="type">Entity type</param>
            public DefaultTypeMap(Type type)
            {
                if (type == null)
                    throw new ArgumentNullException("type");
    
                _fields = GetSettableFields(type);
                _properties = GetSettableProps(type);
                _type = type;
            }
    
            /// <summary>
            /// 获取属性的setter访问器
            /// </summary>
            /// <param name="propertyInfo"></param>
            /// <param name="type"></param>
            /// <returns></returns>
            internal static MethodInfo GetPropertySetter(PropertyInfo propertyInfo, Type type)
            {
                return propertyInfo.DeclaringType == type ?
                    propertyInfo.GetSetMethod(true) :
                    propertyInfo.DeclaringType.GetProperty(
                       propertyInfo.Name,
                       BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
                       Type.DefaultBinder,
                       propertyInfo.PropertyType,
                       propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray(),
                       null).GetSetMethod(true);
            }
    
            /// <summary>
            /// 获取某类型所有可写(有set,包括私有)的成员属性
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            internal static List<PropertyInfo> GetSettableProps(Type t)
            {
                return t
                      .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                      .Where(p => GetPropertySetter(p, t) != null)
                      .ToList();
            }
    
            /// <summary>
            /// 获取某类型所有的成员字段
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            internal static List<FieldInfo> GetSettableFields(Type t)
            {
                return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToList();
            }
    
            /// <summary>
            /// 获取最佳的成员构造器,优先顺序:public的构造器0, 其它构造器1, private的构造器2,然后再按参数匹配
            /// Finds best constructor
            /// </summary>
            /// <param name="names">DataReader column names</param>
            /// <param name="types">DataReader column types</param>
            /// <returns>Matching constructor or default one</returns>
            public ConstructorInfo FindConstructor(string[] names, Type[] types)
            {
                var constructors = _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                foreach (ConstructorInfo ctor in constructors.OrderBy(c => c.IsPublic ? 0 : (c.IsPrivate ? 2 : 1)).ThenBy(c => c.GetParameters().Length))
                {
                    ParameterInfo[] ctorParameters = ctor.GetParameters();
                    if (ctorParameters.Length == 0)
                        return ctor;
    
                    if (ctorParameters.Length != types.Length)
                        continue;
    
                    int i = 0;
                    for (; i < ctorParameters.Length; i++)
                    {
                        if (!String.Equals(ctorParameters[i].Name, names[i], StringComparison.OrdinalIgnoreCase))
                            break;
                        if (types[i] == typeof(byte[]) && ctorParameters[i].ParameterType.FullName == SqlMapper.LinqBinary)
                            continue;
                        var unboxedType = Nullable.GetUnderlyingType(ctorParameters[i].ParameterType) ?? ctorParameters[i].ParameterType;
                        if (unboxedType != types[i]
                            && !(unboxedType.IsEnum && Enum.GetUnderlyingType(unboxedType) == types[i])
                            && !(unboxedType == typeof(char) && types[i] == typeof(string)))
                            break;
                    }
    
                    if (i == ctorParameters.Length)
                        return ctor;
                }
    
                return null;
            }
    
            /// <summary>
            /// 查找带ExplicitConstructorAttribute特性标识的构造器
            /// Returns the constructor, if any, that has the ExplicitConstructorAttribute on it.
            /// </summary>
            public ConstructorInfo FindExplicitConstructor()
            {
                var constructors = _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                var withAttr = constructors.Where(c => c.GetCustomAttributes(typeof(ExplicitConstructorAttribute), true).Length > 0).ToList();
    
                if (withAttr.Count == 1)
                {
                    return withAttr[0];
                }
    
                return null;
            }
    
            /// <summary>
            /// 根据构造函数和列名
            /// Gets mapping for constructor parameter
            /// </summary>
            /// <param name="constructor">Constructor to resolve</param>
            /// <param name="columnName">DataReader column name</param>
            /// <returns>Mapping implementation</returns>
            public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
            {
                var parameters = constructor.GetParameters();
    
                //注意构造器参数名与列名是相同的(忽略大小写)
                return new SimpleMemberMap(columnName, parameters.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)));
            }
    
            /// <summary>
            /// 为某列找到映射关系,返回IMemberMap
            /// Gets member mapping for column
            /// </summary>
            /// <param name="columnName">DataReader column name</param>
            /// <returns>Mapping implementation</returns>
            public SqlMapper.IMemberMap GetMember(string columnName)
            {
                //优先找与列名相同的属性名(优先找大小写相同的,再找不同的)。
                var property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
                   ?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));
    
                //如果找不到,就尝试去掉列名下划线,再找一次。
                if (property == null && MatchNamesWithUnderscores)
                {
                    property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.Ordinal))
                        ?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.OrdinalIgnoreCase));
                }
    
                //如果找到就返回一个成员映射对象
                if (property != null)
                    return new SimpleMemberMap(columnName, property);
    
                //如果没有找到匹配的属性,就找DomainObject.Field,按照上面的套路再找一次。
                var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
                   ?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));
    
                if (field == null && MatchNamesWithUnderscores)
                {
                    field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.Ordinal))
                        ?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.OrdinalIgnoreCase));
                }
    
                if (field != null)
                    return new SimpleMemberMap(columnName, field);
    
                return null;
            }
            /// <summary>
            /// 按列名匹配属性时,忽略下划线(有些时习惯在数据库中使用下划线)。
            /// Should column names like User_Id be allowed to match properties/fields like UserId ?
            /// </summary>
            public static bool MatchNamesWithUnderscores { get; set; }
        }
  • 相关阅读:
    JAVA学习---JAVA基础元素
    JAVA开发-eclipse打开失败:A Java Runtime Environment(JRE) or Java Development Kit(JDK) must be available……的解决办法
    文章转载---西工大博士生文言文答辩致谢
    python中正则匹配之re模块
    python中random模块的使用
    python中函数的定义及调用
    Python中字符编码及转码
    python中字符串输出格式
    数据库与表的剩余操作
    线程其他相关用法和守护线程
  • 原文地址:https://www.cnblogs.com/shi5588/p/4128194.html
Copyright © 2020-2023  润新知