You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

合并增改操作中编辑时创建字段赋值的性能优化问询

优化方案

核心问题是针对每个编辑项重复发起3次数据库查询,造成了不必要的性能损耗。我们可以通过批量预查询+内存字典匹配的方式解决,只需要1次数据库请求就能获取所有需要的历史字段值。

具体实现步骤:

  1. 先筛选出所有需要编辑的记录ID(即x.Id != 0的项)
  2. 批量查询这些ID对应的CreateDateTime、CreatedBy、CreatedIp字段,将结果存入以ID为键的字典中
  3. 构建实体对象时,直接从字典中读取历史值,避免重复访问数据库

优化后的代码示例:

// 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:52:44