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

Entity Framework高效查询优化:如何仅获取指定Revision关联数据?

EF查询优化方案:仅获取指定Revision的关联数据

问题根源

  • 当前代码通过GetAll拉取全部RevisionEEPROM实体及关联的Pages、PageLines到内存,再本地过滤指定ID的记录,完全浪费了数据库的查询优化能力,数据量越大性能越差。
  • ViewModel中使用.Result阻塞异步方法,容易引发死锁和线程卡顿问题。

优化步骤

1. 给通用数据服务增加过滤查询能力

在GenericDataService中新增支持Lambda过滤的方法,让筛选逻辑在数据库层面执行,只拉取需要的数据:

public async Task<IEnumerable<T>> GetWhere(Expression<Func<T, bool>> predicate, string[] includes = null)
{
    using (var context = _contexFactory.CreateDbContext())
    {
        var query = context.Set<T>().AsQueryable();
        
        // 处理关联数据加载
        if (includes != null)
        {
            foreach (var include in includes)
                query = query.Include(include);
        }
        
        // 应用过滤条件并异步加载结果
        return await query.Where(predicate).ToListAsync();
    }
}

2. 修改数据服务的查询逻辑

修改GetEEPROMPages方法,直接查询指定ID的RevisionEEPROM,避免全量拉取:

public async Task<List<Page>> GetEEPROMPages(int eepromRevId)
{
    // 只需指定最深层关联路径,EF会自动包含父级的Pages
    string[] includes = { "Pages.PageLines" };
    
    // 直接在数据库筛选目标Revision
    var targetRevision = (await dataService.GetWhere(r => r.Id == eepromRevId, includes)).FirstOrDefault();
    
    // 返回关联的Pages集合,空判断避免空引用异常
    return targetRevision?.Pages.ToList() ?? new List<Page>();
}

3. 修复ViewModel的异步调用问题

替换.Result为await,避免线程阻塞:

// 若为UI事件处理方法可保留async void,其他场景建议用async Task
private async void GetRevisionData(int revisionId) 
{
    List<Page> eepromPages = await revisionEEPROMDataService.GetEEPROMPages(revisionId);
    // 后续处理eepromPages逻辑
}

额外优化建议

  • 投影查询:如果只需要Page和PageLine的部分字段,可直接投影到DTO,减少数据库传输的数据量:
    public async Task<List<PageDto>> GetEEPROMPages(int eepromRevId)
    {
        using (var context = _contexFactory.CreateDbContext())
        {
            return await context.Set<RevisionEEPROM>()
                .Where(r => r.Id == eepromRevId)
                .SelectMany(r => r.Pages)
                .Select(p => new PageDto
                {
                    Id = p.Id,
                    PageNumber = p.PageNumber,
                    Lines = p.PageLines.Select(pl => new PageLineDto
                    {
                        Id = pl.Id,
                        Content = pl.Content
                    }).ToList()
                })
                .ToListAsync();
        }
    }
    
  • 无跟踪查询:如果查询到的实体不需要修改,可添加.AsNoTracking()减少EF的实体跟踪开销:
    var query = context.Set<T>().AsNoTracking().AsQueryable();
    

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:30:25