API调用后无法获取数据库最新值的问题排查与解决
问题原因
这是EF Core的**一级缓存(DbContext 跟踪缓存)**导致的:
AppA的整个请求生命周期内使用的是同一个UnitOfWork(对应同一个DbContext实例),第一次查询MasterBOFlightBooking时,EF会把查询到的实体存入ChangeTracker缓存。后续即使数据库被AppB修改,再次查询同一主键的实体时,EF会直接返回缓存里的旧实例,不会主动去数据库拉取最新数据。
解决方案
给出几种可行的处理方式,按需选择:
1. 查询时跳过缓存(推荐)
在第二次查询时添加AsNoTracking(),让EF不使用缓存,直接从数据库获取最新数据:
// 重新查询时添加AsNoTracking() bookingInfo = await _unitOfWork.MasterBOFlightBookingRepository .Where(x => x.TravelmateId == "TF67271" && x.IsPrimaryPsgnr == true) .AsNoTracking() .FirstOrDefaultAsync();
如果希望所有查询都不使用缓存,也可以在Repository的查询逻辑里默认加上AsNoTracking()。
2. 手动刷新实体缓存
如果需要保留实体跟踪,可以在第二次查询前,手动刷新已缓存的实体:
// 先获取缓存中的实体(如果存在) var cachedEntity = _unitOfWork.MasterBOFlightBookingRepository .Local .FirstOrDefault(x => x.TravelmateId == "TF67271" && x.IsPrimaryPsgnr == true); if (cachedEntity != null) { // 从数据库刷新该实体 await _unitOfWork.DbContext.Entry(cachedEntity).ReloadAsync(); } // 再执行查询,此时会返回刷新后的实体 bookingInfo = await _unitOfWork.MasterBOFlightBookingRepository .Where(x => x.TravelmateId == "TF67271" && x.IsPrimaryPsgnr == true) .FirstOrDefaultAsync();
注:需要确保UnitOfWork暴露了内部的DbContext实例。
3. 清空DbContext的跟踪缓存
如果当前请求中不需要保留其他跟踪实体,可以直接清空ChangeTracker的缓存:
// 清空所有跟踪的实体 _unitOfWork.DbContext.ChangeTracker.Clear(); // 再执行查询 bookingInfo = await _unitOfWork.MasterBOFlightBookingRepository .Where(x => x.TravelmateId == "TF67271" && x.IsPrimaryPsgnr == true) .FirstOrDefaultAsync();
4. 使用新的UnitOfWork实例
如果UnitOfWork是通过依赖注入创建的,可以通过工厂模式获取一个新的实例,确保第二次查询使用全新的DbContext:
// 假设注入了IUnitOfWorkFactory var newUnitOfWork = _unitOfWorkFactory.Create(); bookingInfo = await newUnitOfWork.MasterBOFlightBookingRepository .Where(x => x.TravelmateId == "TF67271" && x.IsPrimaryPsgnr == true) .FirstOrDefaultAsync(); // 使用后记得释放(如果需要) await newUnitOfWork.DisposeAsync();
内容的提问来源于stack exchange,提问作者Thanh Nguyen
相关产品推荐
相关产品推荐

