C#如何使用Dapper操作数据库_C#轻量级ORM框架Dapper教程【实战】
使用Dapper需注意:显式调用connection.Open();SQL列名与C#属性区分大小写,建议加AS别名;QueryAsync()懒执行,需await或ToList();多结果集用QueryMultiple(),按顺序Read(),用using释放连接。
说个容易踩的坑:用Dapper的时候,connection.Open()这一步必须你亲自来,它不像某些框架那样“贴心”地帮你自动打开连接。Dapper的“轻量”哲学就是——它只管执行,不管后勤。要是忘了显式调用Open(),一跑查询直接就给你甩个InvalidOperationException: Connection is not open。这事儿虽然小,但第一次碰上确实挺懵的。

所以,第一条铁律:必须显式调用 connection.Open(),否则所有查询都会直接抛出 InvalidOperationException: Connection is not open —— Dapper 从不帮你开连接,这是它“轻量”的代价,也是你最容易栽的第一个坑。
为什么 Query() 返回空列表或全是默认值
问题多半不在SQL本身,而是数据库列名和C#属性名之间那点“小误会”。Dapper默认走的字面精确匹配,而且它特别较真——区分大小写。它不会自动帮你把下划线转成驼峰,也不认[Column]或[JsonProperty]这类特性。
- 在PostgreSQL或MySQL(
lower_case_table_names=0)里,user_id和UserId完全是两码事 - SQL Server虽然通常不敏感,但别赌——不同的排序规则或显式设置都可能让你翻车
- 最稳妥的做法:在SQL里加
AS别名,比如SELECT user_id AS UserId, created_at AS CreatedAt FROM users,一劳永逸 - 想全局统一?那就得手动注册映射器:
SqlMapper.SetTypeMap(typeof(User), new ColumnAttributeTypeMapper。当然,Dapper本身不提供现成的实现,得自己动手写一个())
QueryAsync() 报 “Invalid operation on a closed reader” 怎么办
这个错误的潜台词很简单:你返回了一个还没真正取数据的IEnumerable,而承载它的IDbConnection在你开始遍历之前就已经被关掉了。Dapper的异步枚举是懒执行的,底层的SqlDataReader一旦关闭,你再想读数据,自然就崩了。
- 务必
await调用,不要弄断async/await链 - 别在
using块外返回一个未物化的IEnumerable;实在要返回,就先.ToList()或.ToArray() - Web API里写
return Ok(conn.QueryAsync是个典型的错误——当框架消费结果时,连接早就释放了()) - 如果确实需要延迟执行,那就得确保连接的生命周期覆盖整个消费过程,别指望靠“运气”
多结果集必须用 QueryMultiple(),且 Read() 顺序不能错
QueryMultiple()不是个智能分表工具,它做的只是按SQL语句的顺序把一次响应切成几块。你写了SELECT Orders; SELECT OrderItems,那就必须按顺序来:先multi.Read,再multi.Read。
- 中间插个
Read或者漏读一个,立刻报() InvalidOperationException - 每个
Read返回的是() IEnumerable,不是单个对象;要取第一条数据得接.FirstOrDefault() GridReader必须用using包裹,否则连接不会自动释放,积少成多,连接池容易爆- SQL中多个查询必须用分号分隔,别指望靠注释或换行来分割
真正容易被忽略的核心点在于:Dapper从不过问连接的生命周期,也不做任何SQL改写。你给它什么,它就发什么;你什么时候关连接,直接决定你能不能拿到结果。所谓“轻量”,本质上是把控制权全部交还给你,而不是替你兜底。










































