合并增改操作中编辑时创建字段赋值的性能优化问询
优化方案
核心问题是针对每个编辑项重复发起3次数据库查询,造成了不必要的性能损耗。我们可以通过批量预查询+内存字典匹配的方式解决,只需要1次数据库请求就能获取所有需要的历史字段值。
具体实现步骤:
- 先筛选出所有需要编辑的记录ID(即
x.Id != 0的项) - 批量查询这些ID对应的
CreateDateTime、CreatedBy、CreatedIp字段,将结果存入以ID为键的字典中 - 构建实体对象时,直接从字典中读取历史值,避免重复访问数据库
优化后的代码示例:
// 1. 提取所有待编辑的记录ID var editIds = request.CurrencyType.Where(x => x.Id != 0).Select(x => x.Id).ToList(); var existingCurrencyMap = new Dictionary<int, (DateTime CreateDateTime, string CreatedBy, string CreatedIp)>(); // 2. 批量查询历史字段,仅发起1次数据库请求 if (editIds.Any()) { existingCurrencyMap = _context.BankAccountCurrencies .Where(a => editIds.Contains(a.Id)) .Select(a => new { a.Id, a.CreateDateTime, a.CreatedBy, a.CreatedIp }) .ToDictionary( x => x.Id, x => (x.CreateDateTime, x.CreatedBy, x.CreatedIp) ); } // 3. 构建实体集合,从字典中读取历史值 var currencyList = request.CurrencyType.Select(x => new Sepehr.Domain.Banks.BankAccountCurrencyType { Id = x.Id, Title = x.Title, CreateDateTime = x.Id != 0 ? existingCurrencyMap[x.Id].CreateDateTime : DateTime.Now, CreatedBy = x.Id != 0 ? existingCurrencyMap[x.Id].CreatedBy : request.Actor.UserName, CreatedIp = x.Id != 0 ? existingCurrencyMap[x.Id].CreatedIp : request.Actor.Ip, ModifiedDateTime = x.Id != 0 ? DateTime.Now : null }).ToList(); _context.BankAccountCurrencies.UpdateRange(currencyList); return _context.SaveChanges() > 0;
额外优化建议:
- 可以在批量查询时添加
AsNoTracking(),因为我们仅需读取数据,不需要EF跟踪实体状态,能进一步提升查询性能 - 建议增加
TryGetValue判断(比如existingCurrencyMap.TryGetValue(x.Id, out var existing)),避免因数据库中不存在对应ID导致的KeyNotFoundException,让代码更健壮
内容的提问来源于stack exchange,提问作者Zeynab Rostami
相关产品推荐
相关产品推荐

