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);<br>conn.Open();<br>using var tx = conn.BeginTransaction();<br>try<br>{<br> conn.Execute("INSERT INTO users (name, email) VALUES (@Name, @Email)",<br> new { Name = "Alice", Email = "a@example.com" }, tx);<br> var id = conn.ExecuteScalar<long>("SELECT LAST_INSERT_ID()", transaction: tx);<br> tx.Commit();<br> Console.WriteLine($"新用户ID:{id}");<br>}<br>catch<br>{<br> tx.Rollback();<br> throw;<br>}
用多语句一次执行(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();";<br>var id = conn.ExecuteScalar<long>(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拿结果。不复杂但容易忽略连接复用和事务边界。
