Dapper如何处理MySQL的LAST_INSERT_ID() Dapper获取MySQL自增ID

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

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
拿结果。不复杂但容易忽略连接复用和事务边界。

相关推荐