Dapper 获取 MySQL 自增 ID 的正确方式是 INSERT 后立即用同一连接(推荐加事务)执行 SELECT LAST_INSERT_ID() 并用 ExecuteScalar 获取结果;多语句优化需开启 Allow User Variables;不可依赖 Execute 返回值或 OUTPUT 子句。

Dapper 本身不直接封装 MySQL 的 LAST_INSERT_ID(),但它能通过标准 SQL 执行和返回值机制,安全、高效地获取刚插入记录的自增 ID。关键在于:使用 ExecuteScalar 执行带 SELECT LAST_INSERT_ID() 的语句,或更推荐——在单条语句中用 INSERT ...; SELECT LAST_INSERT_ID()(MySQL 支持多语句)或直接依赖 Dapper 对 ExecuteScalar 插入语句的隐式行为(需配置)。
用 ExecuteScalar 直接查 LAST_INSERT_ID()
这是最清晰、兼容性最好的方式。先执行 INSERT,再立即执行 SELECT LAST_INSERT_ID(),确保在同一个连接和事务上下文中运行:
- 必须复用同一个
IDbConnection实例(不能新开连接) - 建议显式开启事务,避免并发干扰(尤其高并发场景)
- MySQL 的
LAST_INSERT_ID()是连接级变量,只要没被其他 INSERT 覆盖,就安全
示例代码:
using var conn = new MySqlConnection(connStr);
conn.Open();
using var tx = conn.BeginTransaction();
try
{
conn.Execute("INSERT INTO users (name, email) VALUES (@Name, @Email)",
new { Name = "Alice", Email = "a@example.com" }, tx);
var id = conn.ExecuteScalar("SELECT LAST_INSERT_ID()", transaction: tx);
tx.Commit();
Console.WriteLine($"新用户ID:{id}");
}
catch
{
tx.Rollback();
throw;
}
用多语句一次执行(MySQL 特有优化)
MySQL 支持在一个命令中执行多条语句(需连接字符串启用 Allow User Variables=True 或默认允许),Dapper 可用 ExecuteScalar 直接运行 INSERT; SELECT LAST_INSERT_ID():
- 减少一次网络往返,性能略优
- 必须确保连接字符串包含
Allow User Variables=True(部分驱动版本需要) - 注意:不是所有 MySQL 连接库都默认开启多语句支持(如 MySqlConnector 默认允许,Old MySql.Data 需显式设置)
示例:
var sql = @"INSERT INTO users (name, email) VALUES (@Name, @Email); SELECT LAST_INSERT_ID();";
var id = conn.ExecuteScalar(sql, new { Name = "Bob", Email = "b@example.com" });
依赖 Execute 返回值(隐式,需注意驱动行为)
某些 MySQL 驱动(如较新版本的 MySqlConnector)在调用 Execute 插入后,会将自增 ID 自动设为返回值(类似 SQL Server 的 @@IDENTITY)。但 Dapper 的 Execute 方法本身只返回影响行数(int),**不会自动返回 ID** ——除非你用 ExecuteScalar 或驱动扩展了行为。
- 不要依赖
Execute(...)的返回值作为 ID(它返回的是“1”,不是 ID) - 若看到某段代码用
Execute得到 ID,大概率是用了自定义扩展方法或特定驱动的非标行为 - 最稳妥做法始终是显式查
LAST_INSERT_ID()
使用 Output 子句?MySQL 不支持
SQL Server 支持 OUTPUT INSERTED.Id,但 MySQL **没有等效语法**。别尝试写 INSERT ... OUTPUT,会报语法错误。必须用 LAST_INSERT_ID() 方案。
基本上就这些。核心就一条:INSERT 后立刻用同一连接(最好同事务)执行 SELECT LAST_INSERT_ID(),用 ExecuteScalar 拿结果。不复杂但容易忽略连接复用和事务边界。










