<p>Dapper 默认不自动转换数据库列名中的下划线、横线或大小写混杂格式以匹配 C# 驼峰命名属性。推荐优先在 SQL 中用 AS 别名(如 user_name AS UserName)实现精准映射;其次可全局配置 SqlMapper.SetTypeMap 实现下划线转 PascalCase;特殊场景支持自定义 [DbColumn] 特性映射。</p>

Dapper 默认使用 驼峰命名(PascalCase 或 camelCase) 与 .NET 属性名匹配,遇到数据库列名含下划线(如 user_name)、横线、空格或大小写混杂(如 USER_NAME、first-name)时,不会自动映射——除非你显式告诉它怎么对应。
方法一:用别名在 SQL 中重命名列
最直接、推荐的方案:在 SQL 查询中用 AS 给列起一个和 C# 属性名完全一致的别名。
var users = connection.Query<User>(@"
SELECT id AS Id, user_name AS UserName, created_at AS CreatedAt
FROM users
WHERE status = @status", new { status = "active" });
这样 Dapper 就能按属性名精准绑定,不依赖任何配置,兼容性好、性能高、逻辑清晰。
方法二:启用列名自动映射(SqlMapper.SetTypeMap)
通过 SqlMapper.SetTypeMap 自定义类型映射规则,让 Dapper 把带下划线的列名(如 user_name)自动转成 PascalCase(UserName)再匹配属性。
只需设置一次(通常放在应用启动处):
SqlMapper.SetTypeMap(typeof(User), new CustomPropertyTypeMap(
typeof(User),
(type, columnName) => type.GetProperties()
.FirstOrDefault(p => p.Name.Equals(
System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToTitleCase(
columnName.Replace("_", " ")).Replace(" ", ""),
StringComparison.OrdinalIgnoreCase))));
⚠️ 注意:这个逻辑较重,对每个列都要做字符串处理;建议仅用于 legacy 数据库且字段量不大时。生产环境慎用,可能影响性能。
方法三:用 [Column] 特性(需配合 SqlMapper.AddTypeMap)
Dapper 原生不识别 [Column](那是 EF 的),但你可以自己扩展:
- 给实体属性加上自定义特性,比如
[DbColumn("user_name")] - 实现一个继承
ITypeMap的映射器,读取该特性并返回匹配的PropertyInfo - 调用
SqlMapper.SetTypeMap(typeof(User), yourCustomMap)
适合中大型项目统一规范列映射,但开发成本略高,一般小项目没必要。
补充说明:大小写敏感问题
PostgreSQL 默认小写列名,SQL Server 默认不区分大小写,MySQL 取决于系统设置。Dapper 默认是大小写不敏感匹配(靠 StringComparison.OrdinalIgnoreCase),所以 USERNAME、user_name、UserName 在别名方式下都能对上 UserName 属性——前提是 SQL 里用了正确别名。
如果没用别名,又遇到全大写列名(如 Oracle 的 USER_ID),而你的属性叫 UserId,Dapper 默认找不到。此时仍推荐别名法,简单可靠。
基本上就这些。日常开发中,优先用 SQL 别名,清晰可控;需要全局适配再考虑 SetTypeMap;特殊场景才动手写自定义映射器。不复杂但容易忽略,记牢“Dapper 不自动转换下划线”这个前提,就能少踩坑。










