Dapper 下划线映射实体

  • 解决方案
  • 原理
  • 测试
    • 代码
    • 测试结果
  • 总结

解决方案

设置静态变量
DefaultTypeMap.MatchNamesWithUnderscores = true;

原理

dapper将字段映射实体,会先创建DufaultTypeMap,在该类中处理Sql查询字段映射逻辑:

  1. 先查找属性,完全匹配,如果没有匹配到则判断是否进行匹配下划线,最后判断是否存在属性,存在则返回实体成员属性映射关系类;
  2. 如果没有找到属性,就找字段,逻辑同上。
/// <summary>
/// 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.Find(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))?? Properties.Find(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));//判断是否需要进行下划线匹配if (property == null && MatchNamesWithUnderscores){property = Properties.Find(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.Ordinal))?? Properties.Find(p => string.Equals(p.Name, columnName.Replace("_", ""), StringComparison.OrdinalIgnoreCase));}if (property != null)return new SimpleMemberMap(columnName, property);// ... 省略代码
}
 /// <summary>/// Should column names like User_Id be allowed to match properties/fields like UserId ?/// true  User_Id -> UserId ✔/// false User_Id -> UserId X/// </summary>public static bool MatchNamesWithUnderscores { get; set; }

测试

代码

//带下划线
public class UserSimpleWithUnderscores
{                  public string User_Id { get; set; }public string User_Name { get; set; }//测试全字段配置public string Sex { get; set; }
}
//不带下划线
public class UserSimpleNotWithUnderscores
{public string UserId { get; set; }//重命名 不然会抛异常//参考 https://blog.csdn.net/yiquan_yang/article/details/107341252public string UName { get; set; }public string Sex { get; set; }
}
//带下划线和不带 混合
public class UserSimpleMixtureAndRename
{public string User_Id { get; set; }public string UserName { get; set; }public string ReSex { get; set; }
}
[Fact]
public void QueryUnderscores_Not_MatchNamesWithUnderscores()
{var Id = "b4600fb2-61c3-4786-8ba1-9fc5387a8d17";var userWith = _userRepository.QueryModel<UserSimpleWithUnderscores>("select user_id,user_name,sex from user where user_id=@Id", new { Id });//相同查询参数会报错,这里user_name 改为 u_name//参考 https://blog.csdn.net/yiquan_yang/article/details/107341252//_userRepository是调用dapper不用管var userNotWith = _userRepository.QueryModel<UserSimpleNotWithUnderscores>("select user_id,user_name u_name,sex from user where user_id=@Id", new { Id });var userMix = _userRepository.QueryModel<UserSimpleMixtureAndRename>("select user_id,user_name,sex as resex from user where user_id=@Id", new { Id });Assert.NotNull(userWith.User_Id);Assert.NotNull(userWith.User_Name);Assert.NotNull(userWith.Sex);Assert.Null(userNotWith.UserId);Assert.Null(userNotWith.UName);Assert.NotNull(userNotWith.Sex);Assert.NotNull(userMix.User_Id);Assert.Null(userMix.UserName);Assert.NotNull(userMix.ReSex);
}
[Fact]
public void QueryUnderscores_Has_MatchNamesWithUnderscores()
{var Id = "b4600fb2-61c3-4786-8ba1-9fc5387a8d17";DefaultTypeMap.MatchNamesWithUnderscores = true;var userWith = _userRepository.QueryModel<UserSimpleWithUnderscores>("select user_id,user_name,sex from user where user_id=@Id", new { Id });//相同查询参数会报错,这里user_name 改为 u_namevar userNotWith = _userRepository.QueryModel<UserSimpleNotWithUnderscores>("select user_id,user_name u_name,sex from user where user_id=@Id", new { Id });var userMix = _userRepository.QueryModel<UserSimpleMixtureAndRename>("select user_id,user_name,sex as resex from user where user_id=@Id", new { Id });Assert.NotNull(userWith.User_Id);Assert.NotNull(userWith.User_Name);Assert.NotNull(userWith.Sex);Assert.NotNull(userNotWith.UserId);Assert.NotNull(userNotWith.UName);Assert.NotNull(userNotWith.Sex);Assert.NotNull(userMix.User_Id);Assert.NotNull(userMix.UserName);Assert.NotNull(userMix.ReSex);
}
[Fact]
public void QueryUnderscores_NotThenHas_MatchNamesWithUnderscores()
{var Id = "b4600fb2-61c3-4786-8ba1-9fc5387a8d17";var userWith = _userRepository.QueryModel<UserSimpleWithUnderscores>("select user_id,user_name,sex from user where user_id=@Id", new { Id });//相同查询参数会报错,这里user_name 改为 u_namevar userNotWith = _userRepository.QueryModel<UserSimpleNotWithUnderscores>("select user_id,user_name u_name,sex from user where user_id=@Id", new { Id });var userMix = _userRepository.QueryModel<UserSimpleMixtureAndRename>("select user_id,user_name,sex as resex from user where user_id=@Id", new { Id });Assert.NotNull(userWith.User_Id);Assert.NotNull(userWith.User_Name);Assert.NotNull(userWith.Sex);Assert.Null(userNotWith.UserId);Assert.Null(userNotWith.UName);Assert.NotNull(userNotWith.Sex);Assert.NotNull(userMix.User_Id);Assert.Null(userMix.UserName);Assert.NotNull(userMix.ReSex);DefaultTypeMap.MatchNamesWithUnderscores = true;userWith = _userRepository.QueryModel<UserSimpleWithUnderscores>("select user_id,user_name,sex from user where user_id=@Id", new { Id });userNotWith = _userRepository.QueryModel<UserSimpleNotWithUnderscores>("select user_id,user_name u_name,sex from user where user_id=@Id", new { Id });userMix = _userRepository.QueryModel<UserSimpleMixtureAndRename>("select user_id,user_name,sex as resex from user where user_id=@Id", new { Id });Assert.NotNull(userWith.User_Id);Assert.NotNull(userWith.User_Name);Assert.NotNull(userWith.Sex);Assert.Null(userNotWith.UserId);Assert.Null(userNotWith.UName);Assert.NotNull(userNotWith.Sex);Assert.NotNull(userMix.User_Id);Assert.Null(userMix.UserName);Assert.NotNull(userMix.ReSex);
}

测试结果

总结

在Asp.Net Core中在Startup下加入
DefaultTypeMap.MatchNamesWithUnderscores = true;

注:千万不要动态在查询代码中配置,即要求有的查询需要兼容下划线,有的不允许兼容下划线,会非常难控制,参考测试代码第三个例子(将第一个第二个例子实体合并,查询结果是不一样的)。每个实体类进行了缓存

 public static Func<Type, ITypeMap> TypeMapProvider = (Type type) => new DefaultTypeMap(type);public static ITypeMap GetTypeMap(Type type){if (type == null) throw new ArgumentNullException(nameof(type));var map = (ITypeMap)_typeMaps[type];if (map == null){lock (_typeMaps){  map = (ITypeMap)_typeMaps[type];if (map == null){map = TypeMapProvider(type);_typeMaps[type] = map;}}}return map;}// use Hashtable to get free lockless readingprivate static readonly Hashtable _typeMaps = new Hashtable();

注:相似实体抛异常:Dapper Object must implement IConvertible.,相同查询字段不要声明多个实体。

Dapper 下划线相关推荐

  1. Python 单下划线(“_“)与双下划线(“__“)以及以双下划线开头和结尾的的区别

    由于python 中没有java 语言中的private ,public, protected 之类的,就引用了下划线. 单下划线的作用: 以单下划线("_")开头的模块变量或者函 ...

  2. python 下划线转驼峰

    # 下划线转驼峰 def str2Hump(text):arr = filter(None, text.lower().split('_'))res = ''j = 0for i in arr:if ...

  3. 表格下划线怎么加粗_这招高!Excel签名栏的下划线随列宽变化,是不是感觉牛哄哄的?...

    职场牛人的世界总有各种高招,随手蹦出,令人赞叹不已! 今天早上去填一个表格,在输入签名时,突然发现签名处的下划线是随着列宽的变化而自动变化,这绝对是动态的,这是怎么做到的呢? 我特意看了一下这个单元格 ...

  4. Android开发技巧——去掉TextView中autolink的下划线

    我们知道,在布局文件中设置textview的autolink及其类型,这时textivew上会显示link的颜色,并且文字下面会有一条下划线,表示可以点击.而在我们在点击textview时,应用将根据 ...

  5. 42. fastjson处理下划线和驼峰问题的方法和源码分析

    一. 前言 在开发过程中经常遇到json解析和生成的问题,所以用自己也一直用fastjson来实现这个功能. 但是,最近遇到一个问题: json字符串里面的数据很多都是"_"下划线 ...

  6. python双下划线用法详解

    __xxx__:双下划线代表着是系统定义的名字. __xxx:代表着类中的私有变量名. _xxx:不能用"from module import *"导入. Python中存在一些特 ...

  7. 下划线在 Python 中的特殊含义

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 Python 中的下划线 下划线在 Python 中是有特殊含义的 ...

  8. python 中的下划线

    Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from module import *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下 ...

  9. php类属性命名驼峰还是下划线,PHP实现驼峰命名和下划线命名互转

    本篇文章教大家实现驼峰命名和下划线命名互转,在php开发中经常需要两种命名法互相转换,下面为大家提供两种实现方式. 第一种方法效率相对差一些,实现方式如下://驼峰命名转下划线命名 function ...

最新文章

  1. python判断质数的函数并输出_【python基础】|| 用python判断输入的数是否为素数
  2. html如何让tr自动换行,js和css如何让table自动换行但是不是超出td?
  3. Java集合(实现类线程安全性)
  4. lol最克制诺手的英雄_LOL:究竟有没有完美克制诺手的英雄?时光上单或可一战?...
  5. v-model数据绑定分析
  6. jave-1.0.2.jar
  7. latex标记html样式,latex标题字体大小和样式
  8. ArcGIS Pro脚本工具(10)——从图层生成.stylx样式符号
  9. android小程序题目,我要出题app-我要出题小程序预约 _5577安卓网
  10. 缩写月份单词python_月份的英文单词、缩写及由来
  11. 姿态估计1-07:FSA-Net(头部姿态估算)-源码无死角讲解(2)-网络框架整体结构分析
  12. x5开源库后续知识点
  13. win10系统桌面右键新建卡顿、反应慢问题
  14. 小红书直播收益怎么算?有效提高直播收益的小技巧
  15. 百度云SMS发短信接口 PHP版本SDK TP5.0
  16. 转行大数据还是人工智能,哪个发展更好
  17. 不能装载文档控件。请在检查浏览器的选项中检查浏览器的安全设置_网络安全科普 | 如何正确设置浏览器!...
  18. 【GNSS】gfzrnx-用法
  19. matlab求矩阵的谱半径,【什么是矩阵的谱半径?怎么求?】百度-谱半径
  20. Linux下使用Nginx完成虚拟主机配置

热门文章

  1. 杂文:创新,淘宝,马云,阿里,美国,工商局,假货
  2. 那些你可能用得上的在线办公神器
  3. 打开SQL2000安装包没有弹出安装界面
  4. 收敛级数加发散级数是什么情况?
  5. clip python_python中numpy模块下的np.clip()的用法
  6. 获取当日/当月的时间段——js(技能提升)
  7. easyExcell
  8. 刘轩:教你改善自己的生活习惯
  9. 一年中重要的节日列表_一年中所有节日一览表
  10. 打开网页报错:net::ERR_CONTENT_LENGTH_MISMATCH,网页打开时显示不全,需要刷新几次才行