Dapper是一个轻量级的.NET ORM,它本身不负责数据库连接管理,而是建立在ADO.NET的IDbConnection之上。要让Dapper操作MySQL,核心工作是选好MySQL的ADO.NET驱动,并正确建立连接对象。目前社区主流方案是使用MySqlConnector这个纯托管实现,它比官方的MySql.Data在性能和跨平台支持上更优。

一、引入必要的NuGet包
在项目中,我们需要安装两个包:Dapper和MySqlConnector。Dapper提供扩展方法如Query、Execute;MySqlConnector提供MySqlConnection实现。打开包管理器控制台,执行以下命令:
// 使用NuGet命令行安装 // Install-Package Dapper // Install-Package MySqlConnector
如果你使用SDK风格的项目文件,也可以直接编辑csproj,添加如下项。注意版本号可按实际情况调整,但建议Dapper使用2.x以上,MySqlConnector使用2.x以上以获得更好的异步支持。
<ItemGroup> <PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="MySqlConnector" Version="2.3.5" /> </ItemGroup>
选择MySqlConnector而不是MySql.Data,是因为前者在连接池处理、取消令牌支持以及Linux环境下的稳定性表现更好。很多部署到Docker的.NET程序若用旧驱动,会出现SSL握手失败,而MySqlConnector默认配置更友好。
二、编写连接字符串与工厂方法
MySQL连接字符串需要包含服务器地址、库名、用户、密码以及字符集等。一个典型的连接串如下,其中AllowUserVariables允许我们在SQL中使用自定义变量,对于Dapper的动态参数很有用。
using MySqlConnector;
public static class DbFactory
{
private const string ConnStr =
"Server=127.0.0.1;Port=3306;Database=testdb;User=root;Password=123456;" +
"Charset=utf8mb4;AllowUserVariables=true;Pooling=true;MinimumPoolSize=1;MaximumPoolSize=50;";
public static MySqlConnection OpenConnection()
{
var conn = new MySqlConnection(ConnStr);
conn.Open();
return conn;
}
}
上面的工厂方法返回已打开的MySqlConnection。在Dapper操作中,推荐用using块确保连接释放回池。Pooling=true开启连接池,能避免频繁建立TCP连接的开销。如果应用是Web服务,最大池大小应根据并发量调整,一般50到100之间。
需要注意,Charset设置为utf8mb4才能完整支持表情符与特殊汉字。若只用utf8,在MySQL服务端实际是三字节,插入四字节字符会报错。这也是很多新手配置Dapper for MySQL时的隐性坑。
三、使用Dapper执行查询与写入
拿到连接后,即可调用Dapper的扩展方法。下面示例演示参数化查询,避免SQL注入。Dapper会自动将匿名对象属性映射为@参数。
using Dapper;
using System.Linq;
public class UserRepo
{
public User GetById(int id)
{
using var conn = DbFactory.OpenConnection();
var sql = "SELECT id,name,age FROM users WHERE id = @Id";
return conn.QueryFirstOrDefault<User>(sql, new { Id = id });
}
public int AddUser(User u)
{
using var conn = DbFactory.OpenConnection();
var sql = "INSERT INTO users(name,age) VALUES(@Name,@Age); SELECT LAST_INSERT_ID();";
return conn.ExecuteScalar<int>(sql, u);
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
在上面的代码中,QueryFirstOrDefault方法执行查询并映射为User对象,若没有结果返回null。ExecuteScalar用于插入后取回自增主键,比先插入再查max(id)安全且高效。Dapper默认将列名按大小写不敏感匹配属性名,因此数据库用下划线命名时,可借助别名或自定义映射。
写入操作中务必通过参数对象传值,不要拼接字符串。Dapper的参数化在MySqlConnector底层会转为服务端预编译语句,既安全又减少解析成本。对于批量插入,可使用Execute对IEnumerable展开,但超大数据量建议用MySqlBulkCopy扩展。
四、常见配置错误与排查
第一类问题是连接未释放。若每次new MySqlConnection但不using或不Close,连接池会耗尽,报错Too many connections。务必将连接放在using中,或依赖DI容器作用域生命周期。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 无法连接 Authentication method unknown | MySQL 8默认caching_sha2_password,旧驱动不支持 | 换MySqlConnector或服务端改mysql_native_password |
| 中文乱码 | 连接串Charset不对或表字符集不一致 | 统一使用utf8mb4 |
| 查询超时 | 池满或SQL无索引 | 调大MaximumPoolSize,加索引 |
第二类是事务使用不当。Dapper本身不管理事务,需要手动在连接上BeginTransaction并传给Dapper方法。如下片段展示如何保证两步写原子性。
using var conn = DbFactory.OpenConnection();
using var tx = conn.BeginTransaction();
try
{
conn.Execute("UPDATE accounts SET balance=balance-@Amt WHERE id=@Id",
new { Amt = 100, Id = 1 }, tx);
conn.Execute("UPDATE accounts SET balance=balance+@Amt WHERE id=@Id",
new { Amt = 100, Id = 2 }, tx);
tx.Commit();
}
catch
{
tx.Rollback();
throw;
}
通过事务对象传入,Dapper会在同一连接同一事务内执行命令。这种方式比依赖外部ORM的事务更透明,也契合Dapper保持简单的设计哲学。只要把握住驱动选择、连接串、释放与事务四点,Dapper for MySQL的配置就基本无碍。
DapperMySQLMySqlConnector修改时间:2026-08-10 01:30:33