如何编写同步执行SELECT MAX(id)+1与INSERT的EF Core代码避免id重复?
解决并发插入时ID重复的问题
你的代码之所以会出现ID重复异常,是因为查询max(id)+1和执行插入是两次独立的数据库操作,中间存在时间间隙,并发场景下其他请求可能已经插入新数据,导致你计算出的ID已被占用。要实现和目标SQL等价的原子操作,必须让这两个步骤在数据库端一次性完成,避免中间被打断。
解决方案:执行原生SQL语句
直接将目标INSERT语句作为整体执行,利用数据库的原子性保证查询和插入同步完成,示例代码如下:
// 硬编码name值的情况 var insertSql = "insert into events (id, name) values ((select max(id) + 1 from events), 'd')"; await _unitOfWork.EventRepository.ExecuteSqlAsync(insertSql);
如果需要动态传入name参数(避免SQL注入),可以使用参数化查询:
var newName = "d"; var paramSql = "insert into events (id, name) values ((select max(id) + 1 from events), @p0)"; await _unitOfWork.EventRepository.ExecuteSqlAsync(paramSql, newName);
原理说明
这条原生SQL语句会被数据库作为单个命令原子执行:先计算出当前最大ID加1,紧接着完成插入操作,整个过程不会被其他并发请求打断,从根源上避免了ID重复的问题,完全等价于你最初想要执行的SQL逻辑。
内容的提问来源于stack exchange,提问作者ashkufaraz
相关产品推荐
相关产品推荐

