dapper不管理连接状态,必须显式调用connection.open(),否则query/execute抛invalidoperationexception;参数名大小写敏感;多结果集须用querymultiple并严格按序read;字段名默认字面匹配,需sql别名对齐。

连接必须显式打开,否则 Query/Execute 直接报错
Dapper 不接管连接生命周期,connection.Open() 这一步不能跳过。常见错误是 new 了 SqlConnection 就直接调 Query<t>()</t>,结果抛出 InvalidOperationException: Connection is not open。
- 正确写法:在
using块内先调.Open(),再执行任何数据库操作 - 从 EF Core 的
DbContext.Database.GetDbConnection()拿连接时,务必检查conn.State == ConnectionState.Open,EF 可能已关闭它 - 用
using var conn = new SqlConnection(...)但把查询写在块外 → 连接已释放,运行时报ObjectDisposedException
参数名大小写敏感,拼错就绑定失败
Dapper 绑定参数时不校验、不提示,@UserId 和 new { userId = 123 } 会静默失败,最终抛 InvalidOperationException: The parameterized query expects parameter '@UserId'。
- SQL 中的参数名(如
@Name)必须和匿名对象属性名完全一致,包括大小写 - 传
null值时 Dapper 自动转为DBNull.Value,无需手动处理 - 避免用
IDictionary<string object></string>传参——键名大小写易错,且无编译期检查 - 固定值也必须参数化:
WHERE Status = @status,而不是"WHERE Status = 'Active'"
多结果集必须用 QueryMultiple(),且 Read() 顺序不能错
QueryMultiple() 不是智能分表工具,它只是按 SQL 中分号分隔的顺序切分结果集。游标不可回退、不可跳过,乱序或漏读立刻崩。
- SQL 必须用分号分隔多个查询:
"SELECT * FROM Orders; SELECT * FROM OrderItems" - 必须严格按顺序调用:
multi.Read<order>()</order>→multi.Read<orderitem>()</orderitem> - 每个
Read<t>()</t>返回的是IEnumerable<t></t>,不是单个对象;取首项得接.FirstOrDefault() -
GridReader必须用using包裹,否则连接不释放,容易连爆
字段名默认字面匹配,别指望自动驼峰转换
Dapper 默认不做任何列名转换:数据库列 user_name 和 C# 属性 UserName 完全不等价,字段会为 default(T) 或 null。
- 最稳妥做法:SQL 中用
AS显式别名,例如SELECT user_name AS UserName FROM users - PostgreSQL / MySQL(
lower_case_table_names=0)下大小写严格区分,不能靠“一般不敏感”赌运气 -
QueryFirstOrDefault<t>()</t>在无结果时返回default(T)(引用类型为null),不是异常,别误判为失败 - 想全局统一映射需手动注册
SqlMapper.SetTypeMap(),Dapper 本身不提供现成实现
实际写的时候,最容易被忽略的是:Dapper 从不帮你开连接、不改你的 SQL、不猜你的字段名。你写的什么,它就发什么;你关连接的时机,直接决定结果能不能拿到。











