C# Dapper使用方法 C#如何用Dapper查询数据库

来源:这里教程网 时间:2026-02-21 17:41:30 作者:

直接用
IDbConnection.Query<t></t>
最简单

只要数据库连接打开,就能一行代码查出强类型列表。不需要写

SqlCommand
SqlDataReader
或手动映射字段。

常见错误是忘了开连接,或者传了没实现

IDbConnection
的对象(比如直接传
string
连接字符串)。

Query<user></user>
要求返回列名和
User
类的属性名完全匹配(大小写不敏感),否则字段为
null
或默认值
参数用匿名对象传,Dapper 自动转成 SQL 参数,防止 SQL 注入:
new { id = 123 }
如果只查单行,用
QueryFirstOrDefault<t></t>
;查单个值(如
COUNT(*)
),用
QuerySingle<int></int>
using (var conn = new SqlConnection(connectionString))
{
    conn.Open();
    var users = conn.Query<User>("SELECT * FROM Users WHERE Status = @status", 
                                    new { status = "Active" });
}

QueryMultiple
一次执行多个查询

适合主从表、关联数据需要分步处理的场景,比多次

Query
更省网络往返和连接开销。

容易忽略的是必须按顺序读取结果集——先

Read<order>()</order>
,再
Read<orderitem>()</orderitem>
,跳过或乱序会抛
InvalidOperationException

每个
GridReader.Read<t>()</t>
返回一个
IEnumerable<t></t>
,不是单个对象
不能用
QueryMultiple
做跨表 JOIN 后映射到多个类——它不支持自动分割字段,得靠 SQL 的
SELECT ... AS
显式别名 + 多个
Read
记得调用
GridReader.Dispose()
(用
using
最安全)
using (var conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (var multi = conn.QueryMultiple("SELECT * FROM Orders; SELECT * FROM OrderItems;"))
    {
        var orders = multi.Read<Order>().ToList();
        var items = multi.Read<OrderItem>().ToList();
    }
}

动态结果用
Query<dynamic></dynamic>
IDictionary<string object></string>

当表结构不确定、SQL 是拼出来的、或只想快速验证查询逻辑时,避免定义临时类。

注意

dynamic
在运行时解析属性,IDE 没智能提示;而
IDictionary<string object></string>
更明确,且可直接遍历键值对。

Query<dynamic></dynamic>
返回的是
ExpandoObject
,字段访问写法是
row.Name
,但拼错名不会编译报错
Query<idictionary object>></idictionary>
返回每行一个字典,用
row["Name"]
取值,空值处理更可控
两者都不支持 LINQ to Objects 的复杂操作(如嵌套
Select
),建议尽早转成实体类
var rows = conn.Query<IDictionary<string, object>>(
    "SELECT TOP 5 Name, CreatedAt FROM Users ORDER BY Id");
foreach (var row in rows)
{
    Console.WriteLine($"{row["Name"]} - {row["CreatedAt"]}");
}

异步查询必须用
QueryAsync
系列方法

别在

async
方法里混用同步的
Query
,会阻塞线程池线程,尤其在 Web API 高并发下容易拖垮吞吐量。

典型坑是忘了

await
,或用了
.Result
强制同步等待,导致死锁(尤其 ASP.NET Core 旧版本或 UI 线程上下文)。

对应同步方法名加
Async
后缀:
QueryAsync
ExecuteAsync
QueryMultipleAsync
连接对象本身不用特别配置,但确保数据库驱动支持异步(如
Microsoft.Data.SqlClient
,不是已淘汰的
System.Data.SqlClient
异步方法返回
Task<ienumerable>></ienumerable>
,必须
await
,不要用
GetAwaiter().GetResult()
public async Task<IList<User>> GetActiveUsersAsync(string connStr)
{
    using var conn = new SqlConnection(connStr);
    await conn.OpenAsync();
    return (await conn.QueryAsync<User>(
        "SELECT * FROM Users WHERE Status = @status", 
        new { status = "Active" })).AsList();
}

Dapper 的核心就三件事:开连接、写 SQL、选对 Query 方法。最常出问题的地方不在语法,而在连接生命周期管理、字段名匹配规则、以及异步/同步混用——这些地方一旦疏忽,错误往往不直接报在 Dapper 上,而是表现为超时、空数据、或线程卡死。

相关推荐