EF Core 7如何解决并发场景下插入或更新的主键冲突问题?
解决EF Core 7并发场景下主键冲突的UPSERT方案
方案1:使用数据库原生UPSERT语句(推荐,原子操作)
对于SQL Server,可直接使用MERGE语句实现原子性的插入或更新,从数据库层面彻底避免竞态条件。示例代码:
var sql = @" MERGE dbo.Visitors AS Target USING (VALUES (@Id, @Url, @Source)) AS Source (Id, Url, Source) ON Target.Id = Source.Id WHEN MATCHED THEN UPDATE SET Url = Source.Url, Source = Source.Source -- 补充其他需要更新的属性 WHEN NOT MATCHED THEN INSERT (Id, Url, Source) VALUES (Source.Id, Source.Url, Source.Source); "; await db.Database.ExecuteSqlAsync(sql, new SqlParameter("@Id", entity.Id), new SqlParameter("@Url", entity.Url), new SqlParameter("@Source", entity.Source) // 补充对应参数 );
这种方式直接在数据库端完成原子操作,不会出现并发冲突,是性能和可靠性最优的方案。
方案2:尝试更新后插入+异常捕获
先尝试更新记录,若未找到匹配记录则执行插入;若插入时触发主键冲突,捕获异常后再次尝试更新。这种方式利用异常处理兜底,适用于不想编写原生SQL的场景:
try { var updatedCount = await db.Visitors .Where(v => v.Id == entity.Id) .ExecuteUpdateAsync(setters => setters .SetProperty(v => v.Url, entity.Url) .SetProperty(v => v.Source, entity.Source) // 补充其他属性更新逻辑 ); if (updatedCount == 0) { db.Visitors.Add(entity); await db.SaveChangesAsync(); } } catch (DbUpdateException ex) when (ex.InnerException is SqlException sqlEx && sqlEx.Number == 2627) { // 捕获SQL Server主键冲突错误(错误码2627),再次执行更新 await db.Visitors .Where(v => v.Id == entity.Id) .ExecuteUpdateAsync(setters => setters .SetProperty(v => v.Url, entity.Url) .SetProperty(v => v.Source, entity.Source) // 补充其他属性更新逻辑 ); }
注意:不同数据库的主键冲突错误码不同,需根据使用的数据库调整判断条件。
方案3:提升事务隔离级别
之前使用事务无效是因为默认ReadCommitted隔离级别下,后续事务无法读取未提交的新记录。可将隔离级别提升为RepeatableRead或Serializable,强制后续事务等待前一个事务完成后再执行查询:
using var transaction = await db.Database.BeginTransactionAsync(System.Data.IsolationLevel.RepeatableRead); try { var entityDB = await db.Visitors.FindAsync(entity.Id); if (entityDB is not null) { entityDB.Url = entity.Url; entityDB.Source = entity.Source; // 补充其他属性更新逻辑 } else { db.Visitors.Add(entity); } await db.SaveChangesAsync(); await transaction.CommitAsync(); } catch { await transaction.RollbackAsync(); throw; }
此方式会降低并发性能,因为事务会锁住资源导致后续请求等待,仅适用于并发量较低的场景。
内容的提问来源于stack exchange,提问作者sDima
相关产品推荐
相关产品推荐

