如何在Dapper.Contrib中正确实现表名单数化匹配?
解决Dapper.Contrib自动复数化表名(无需修改POCO类)的问题
你遇到的问题是Dapper.Contrib默认会把POCO类名复数化来生成表名,但你的数据库表是单数命名,而且POCO是自动生成的不能手动修改——用SqlMapperExtensions.TableNameMapper全局配置是最适合你的方案,之前没生效应该是因为设置位置不对,下面给你详细的正确实现方式:
1. 全局设置表名映射委托
SqlMapperExtensions.TableNameMapper是一个静态委托,只需要在应用启动时设置一次,不需要在每次创建数据库连接时重复设置。你之前在连接内部设置可能导致它没在Dapper初始化前生效,所以逻辑不起作用。
2. 实现单数表名的映射逻辑
因为你的POCO类名和数据库表名完全一致,直接返回类的名称即可,不需要复杂的字符串处理。如果以后遇到特殊场景(比如少数表名和类名不一致),也可以在这个委托里扩展判断逻辑。
3. 完整的修改后代码
using Dapper.Contrib.Extensions; using System.Collections.Generic; using System.Data.SqlClient; public class Student { public int StudentId {get; set;} public string FirstName {get; set;} public string LastName {get; set;} } class Program { static void Main(string[] args) { // 全局设置表名映射:直接返回类名(单数),替代默认的复数化逻辑 SqlMapperExtensions.TableNameMapper = (type) => type.Name; var students = new List<Student>() { new Student { StudentId = 1, FirstName = "John", LastName = "Doe"}, new Student { StudentId = 2, FirstName = "Tony", LastName = "Montana"} }; long result; // 替换成你的实际连接字符串 string connString = "your_connection_string_here"; using (var cn = new SqlConnection(connString)) { result = cn.Insert(students); } } }
4. 验证效果
设置这个委托后,Dapper.Contrib在生成Insert/Update/Delete语句时,会直接使用Student作为表名,而不是默认的Students,这样就不会再抛出Invalid object name 'Students'的异常了。
补充说明
- 这个方案完全不需要修改自动生成的POCO类,即使以后用
Scaffold-DbContext重新生成类,也不会影响配置,完美适配你的开发流程。 - 如果后续有个别表名和类名不一致的情况,可以在映射委托里添加条件判断,比如:
SqlMapperExtensions.TableNameMapper = (type) => { if (type.Name == "SpecialClass") return "SpecialTableName"; return type.Name; };
内容的提问来源于stack exchange,提问作者Elshad Shabanov
相关产品推荐
相关产品推荐

