EntityFrameworkCore未调用SaveChanges时FindAsync无法查询新插入记录如何解决
解决方案
问题根源
你遇到的重复插入问题本质是:默认EF Core的普通查询(FirstOrDefaultAsync/Where等)仅会请求数据库中已持久化的记录,你调用InsertAsync后未执行SaveChangesAsync时,新增的库存实体仅存在于DbContext的本地追踪缓存中,不会被数据库查询返回。如果你封装的FindAsync方法没有优先查询本地缓存,自然无法匹配到刚插入的未提交记录。
修复方案
方案1:修改FindAsync实现,优先查询本地缓存
调整仓储层的FindAsync逻辑,先查DbSet.Local(当前上下文追踪的所有实体,含未提交的新增/修改实体),本地不存在再查数据库:
// 仓储层的FindAsync实现示例 public async Task<Stock> FindAsync(int productId) { // 优先匹配本地未提交的实体 var localStock = _dbContext.Set<Stock>().Local.FirstOrDefault(s => s.ProductId == productId); if (localStock != null) { return localStock; } // 本地无匹配再发起数据库查询 return await _dbContext.Set<Stock>().FirstOrDefaultAsync(s => s.ProductId == productId); }
如果你的FindAsync是按Stock主键查询,直接调用EF Core原生的FindAsync即可,该方法原生自带本地缓存优先的逻辑,无需额外适配。
方案2:优化提交逻辑,循环外统一保存
你不需要在foreach内部每次调用SaveChangesAsync,所有实体处理完成后统一提交一次即可,大幅提升性能:
foreach (var product in products) { var stock = await stockRepository.FindAsync(product.Id); if (stock == null) { stock = new Stock(SequenceGenerator.Create(SequenceType.Default), product.Id, quantity); await stockRepository.InsertAsync(stock); } else { stock.Quantity += quantity; // 已被上下文追踪的实体无需手动调用UpdateAsync,EF会自动检测属性变更 } } // 所有业务逻辑处理完成后统一提交 await uow.SaveChangesAsync();
可选优化:内存聚合重复产品,减少查询次数
如果你的产品列表存在大量重复ID,可先在内存聚合每个产品的总操作数量,避免重复查询:
// 先聚合同一产品的总新增数量,根据你的业务逻辑调整计算规则 var productQuantityDic = products .GroupBy(p => p.Id) .ToDictionary(g => g.Key, g => g.Sum(_ => quantity)); foreach (var (productId, totalQuantity) in productQuantityDic) { var stock = await stockRepository.FindAsync(productId); if (stock == null) { stock = new Stock(SequenceGenerator.Create(SequenceType.Default), productId, totalQuantity); await stockRepository.InsertAsync(stock); } else { stock.Quantity += totalQuantity; } } await uow.SaveChangesAsync();
内容的提问来源于stack exchange,提问作者Enes Köroğlu
相关产品推荐
相关产品推荐

