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

如何在Entity Framework中针对该场景缓存数据表,仅发起一次数据库调用

问题描述

现有如下代码:

var fdPositions = dbContext.FdPositions.Where(s => s.LastUpdated > DateTime.UtcNow.AddDays(-1));

foreach (JProperty market in markets)
{
    // bunch of logic that is irrelevant here
    var fdPosition = fdPositions.Where(s => s.Id == key).FirstOrDefault();

    if (fdPosition is not null)
    {
        fdPosition.OddsDecimal = oddsDecimal;
        fdPosition.LastUpdated = DateTime.UtcNow;
    }
    else
    {
        // bunch of logic that is irrelevant here
    }
}

await dbContext.SaveChangesAsync();

遍历约10000个markets时,每次循环都会执行var fdPosition = fdPositions.Where(s => s.Id == key).FirstOrDefault();发起一次数据库调用,总计约10000次请求。

需求是仅在var fdPositions = dbContext.FdPositions.Where(s => s.LastUpdated > DateTime.UtcNow.AddDays(-1));这一行发起一次数据库调用,将数据加载到本地缓存,后续循环直接在本地查询匹配对象,同时确保修改后的对象能通过await dbContext.SaveChangesAsync();正确同步至数据库。

解决方案

核心是将EF的IQueryable转为本地字典集合,实现单次数据库查询+高效本地匹配,具体修改如下:

// 一次性加载符合条件的数据到内存,并转为以Id为键的字典(仅发起一次数据库请求)
var fdPositionsDict = dbContext.FdPositions
    .Where(s => s.LastUpdated > DateTime.UtcNow.AddDays(-1))
    .ToDictionary(s => s.Id);

foreach (JProperty market in markets)
{
    // bunch of logic that is irrelevant here
    // 直接从本地字典查询,无额外数据库请求
    if (fdPositionsDict.TryGetValue(key, out var fdPosition))
    {
        fdPosition.OddsDecimal = oddsDecimal;
        fdPosition.LastUpdated = DateTime.UtcNow;
    }
    else
    {
        // bunch of logic that is irrelevant here
    }
}

await dbContext.SaveChangesAsync();

关键说明

  • ToDictionary()方法会立即执行IQueryable的查询,将数据加载到内存中,全程仅发起一次数据库请求。
  • 字典的TryGetValue方法查询效率为O(1),比在普通List中遍历查找更高效,适配10000次循环的场景。
  • 从字典中取出的fdPosition仍然被EF的DbContext追踪,修改属性后调用SaveChangesAsync()会自动将变更同步到数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:20:52