关于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; }
    }
时间: 2024-10-08 02:07:28

关于Dapper的使用笔记3的相关文章

关于Dapper的使用笔记2

public class t_SoDtl { [System.ComponentModel.Description("KeySeq")] public Guid ID { get; set; } //数据库中的列名KeySeq [System.ComponentModel.Description("SoKeySeq")] public Guid SoKeySeq { get; set; } [System.ComponentModel.Description(&qu

关于Dapper的使用笔记1

******************************************************************** 1.Execute a query and map the results to a strongly typed List Note: all extension methods assume the connection is already open, they will fail if the connection is closed. public 

Dapper学习笔记(一)

https://github.com/StackExchange/dapper-dot-net Dapper是对IDbConnection的扩展,需要使用Dapper提供的扩展只需要把SqlMapper这个文件放到自己的项目中即可.这样项目中的IDbConnection就可以直接使用Dapper中的扩展方法,这是怎么实现的呢?百度才知道这个是C#提供的扩展方法. 扩展方法如何使用呢?直接看代码. 对Object写一个自定义的ToString()方法,输出"自定义Object的ToString()

Dapper学习笔记(2)-链接引用

在研究Dapper源码时发现Dapper NET45类库中的SqlMapper.cs文件前面有个蓝色的箭头图标,发现在Dapper NET45文件夹下根本不存在SqlMapper.cs文件,其文件属性中的完整路径指向了Dapper NET40文件夹中的SqlMapper.cs文件,如下图: 后发现其为一个链接引用,代码文件只有一份,但是可以被多个项目所包含.在项目里面添加一个已存在的文件时选择“添加为链接”即可,具体操作如下:

Dapper 学习笔记

一.基础 1.Dapper代码就一个SqlMapper.cs文件, 前人测试Dapper速度较快 的Orm,读取速度接近IDataReader,超过DataTable. 2.a.下载地址 https://github.com/StackExchange/dapper-dot-net ,包含在线示例 (test project).b.net 下可以通过 Nuget下载. 3.实体类用NHibernateMappingGenerator生成. 二.示例代码 1.sql脚本 USE [FactoryD

Dapper学习笔记(4)-事务

Dapper中对事务的处理也非常简单,如下代码所示: 1 private void DapperTransaction() 2 { 3 using (IDbConnection con = OpenConnection()) 4 { 5 IDbTransaction tran = con.BeginTransaction(); 6 try 7 { 8 string query = "update T_Role set RoleName='开发主管' where RoleId=4";//

一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.supervisor.mysql环境搭建搭建好了.net core linux的相关环境,今天就来说说ef core相关的配置及迁移: 简介: Entity Framework(以下简称EF) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,EF Core是Entity

Dapper

Dapper简明教程 Dapper是一款轻量级的ORM框架,有关Dapper优缺点的文章网上一大堆,这里小编就不再赘述啦.下面直接进入正题: 使用前准备 添加对Dapper的引用 在使用Dapper之前,我们要首先添加对Dapper的引用,这里小编使用NuGet来添加引用.因为小编使用的是MySQL数据库,所以也要在项目中添加对MySql.Data的引用. Dapper是一款ORM框架,用于数据表和实体模型间的映射,所以在使用前我们还需要创建数据表和实体模型. 创建数据表 CREATE TABL

Dapper使用

公司的项目使用了Dapper做数据库连接处理,感觉不错,自己研究一下怎么用. 在网上找了找资料对Dapper都比较推崇.主要是两个方面,一个是连接速度很快,一个是代码开源且简单,只有一个SqlMapper.cs文件,是一个轻型的ORM类. 从这篇博客里面找到它的一些介绍和使用方式,但奈何英文太差,只好自己再做个笔记.http://www.cnblogs.com/yipu/archive/2012/11/21/2780199.html 首先从GitHub上获取Dapper:https://gith