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

使用Entity Framework Core一次性获取多表数据填充SelectList的方法

当然有更优化的方案!你当前的写法确实会触发4次独立的数据库查询,每次都要和数据库建立往返,在高并发场景下会额外消耗数据库资源和网络时间。我们可以从减少数据库往返次数、优化数据加载这两个方向来改进:

优化方案1:异步并行加载,减少总耗时

首先推荐使用异步编程模型(ASP.NET Core页面/控制器的异步方法是最佳实践),通过并行加载所有需要的数据集,让数据库可以同时处理这些查询,总耗时会远小于串行执行四次查询的时间。同时,我们只选择需要的Id和Nome字段,避免加载整个实体的冗余数据:

public async Task OnGetAsync()
{
    // 启动四个并行的查询任务,只获取需要的字段
    var celulasTask = _context.Celulas.Select(c => new { c.Id, c.Nome }).ToListAsync();
    var uapTask = _context.UAP.Select(u => new { u.Id, u.Nome }).ToListAsync();
    var referenciasTask = _context.Referencias.Select(r => new { r.Id, r.Nome }).ToListAsync();
    var celulaTiposTask = _context.CelulaTipos.Select(ct => new { ct.Id, ct.Nome }).ToListAsync();

    // 等待所有查询完成
    await Task.WhenAll(celulasTask, uapTask, referenciasTask, celulaTiposTask);

    // 构建SelectList并赋值给ViewData
    ViewData["CelulaId"] = new SelectList(await celulasTask, "Id", "Nome");
    ViewData["UAPId"] = new SelectList(await uapTask, "Id", "Nome");
    ViewData["ReferenciaId"] = new SelectList(await referenciasTask, "Id", "Nome");
    ViewData["CelulaTipoId"] = new SelectList(await celulaTiposTask, "Id", "Nome");
}
优化方案2:添加缓存,彻底减少数据库查询

如果这些下拉列表的数据是不经常变动的基础数据(比如分类、类型这类静态数据),可以把这些数据缓存到内存中,后续请求直接从缓存读取,完全避免数据库查询:

首先需要注入IMemoryCache(在页面模型的构造函数中):

private readonly YourDbContext _context;
private readonly IMemoryCache _cache;

public YourPageModel(YourDbContext context, IMemoryCache cache)
{
    _context = context;
    _cache = cache;
}

然后修改OnGetAsync方法:

public async Task OnGetAsync()
{
    // 定义缓存键,确保唯一
    var cacheKey = "Dropdown_SelectLists_Data";
    
    // 从缓存获取数据,不存在则查询数据库并缓存
    var dropdownData = await _cache.GetOrCreateAsync(cacheKey, async entry =>
    {
        // 设置缓存过期时间,根据数据更新频率调整(比如1小时)
        entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
        
        // 并行加载数据
        var celulas = await _context.Celulas.Select(c => new { c.Id, c.Nome }).ToListAsync();
        var uap = await _context.UAP.Select(u => new { u.Id, u.Nome }).ToListAsync();
        var referencias = await _context.Referencias.Select(r => new { r.Id, r.Nome }).ToListAsync();
        var celulaTipos = await _context.CelulaTipos.Select(ct => new { ct.Id, ct.Nome }).ToListAsync();
        
        return new 
        {
            Celulas = celulas,
            UAP = uap,
            Referencias = referencias,
            CelulaTipos = celulaTipos
        };
    });

    // 构建SelectList
    ViewData["CelulaId"] = new SelectList(dropdownData.Celulas, "Id", "Nome");
    ViewData["UAPId"] = new SelectList(dropdownData.UAP, "Id", "Nome");
    ViewData["ReferenciaId"] = new SelectList(dropdownData.Referencias, "Id", "Nome");
    ViewData["CelulaTipoId"] = new SelectList(dropdownData.CelulaTipos, "Id", "Nome");
}
同步版本(不推荐,但如果必须用)

如果因为某些原因不能使用异步方法,至少要先把所有需要的数据加载到内存,同时只选择必要字段:

public void OnGet()
{
    // 先加载所有需要的数据到内存(仍然是4次查询,但只取必要字段)
    var celulas = _context.Celulas.Select(c => new { c.Id, c.Nome }).ToList();
    var uap = _context.UAP.Select(u => new { u.Id, u.Nome }).ToList();
    var referencias = _context.Referencias.Select(r => new { r.Id, r.Nome }).ToList();
    var celulaTipos = _context.CelulaTipos.Select(ct => new { ct.Id, ct.Nome }).ToList();

    // 构建SelectList
    ViewData["CelulaId"] = new SelectList(celulas, "Id", "Nome");
    ViewData["UAPId"] = new SelectList(uap, "Id", "Nome");
    ViewData["ReferenciaId"] = new SelectList(referencias, "Id", "Nome");
    ViewData["CelulaTipoId"] = new SelectList(celulaTipos, "Id", "Nome");
}
关键优化点总结
  • 减少数据传输:用Select()投影只获取Id和Nome,避免加载实体的其他冗余字段
  • 并行加载:通过Task.WhenAll()让多个查询并行执行,降低总耗时
  • 缓存静态数据:对不经常变动的基础数据添加缓存,彻底减少数据库查询次数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:51:10