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

能否将缓存的同步查询结果用于多个异步查询方法?

当然可以实现

核心思路

先确保Foo()的缓存逻辑正确,然后在各个异步方法中直接复用该方法返回的内存数据,执行Linq操作后包装为异步任务返回即可。如果数据库查询本身是IO密集型操作,建议将Foo()改为异步方法,更符合.NET异步编程规范。

实现示例

1. 同步版Foo()(缓存+数据库查询)

private readonly IMemoryCache _cache;
private readonly YourDbContext _dbContext;

public YourService(IMemoryCache cache, YourDbContext dbContext)
{
    _cache = cache;
    _dbContext = dbContext;
}

// 主查询方法:优先从缓存取,无缓存则查库并存缓存
public List<MyCustomClass> Foo()
{
    const string cacheKey = "MyCustomClass_AllData";
    return _cache.GetOrCreate(cacheKey, entry =>
    {
        // 设置缓存策略,比如滑动过期30分钟
        entry.SlidingExpiration = TimeSpan.FromMinutes(30);
        // 从数据库同步查询数据
        return _dbContext.MyCustomClasses.ToList();
    });
}

2. 基于同步Foo()的异步业务方法

如果仅需对内存数据做Linq处理,直接用Task.FromResult包装结果即可返回异步任务:

// 示例A:过滤数据
public Task<List<MyCustomClass>> MyAmazingMethodA(int targetId)
{
    var allData = Foo();
    var filteredData = allData.Where(item => item.Id == targetId).ToList();
    return Task.FromResult(filteredData);
}

// 示例Z:分组+转换
public Task<List<GroupedResultDto>> MyAmazingMethodZ()
{
    var allData = Foo();
    var groupedData = allData.GroupBy(item => item.Category)
                             .Select(g => new GroupedResultDto
                             {
                                 Category = g.Key,
                                 ItemCount = g.Count()
                             })
                             .ToList();
    return Task.FromResult(groupedData);
}

3. 更推荐的异步版FooAsync()

因为数据库查询是IO操作,异步实现能避免阻塞线程,优化资源利用率:

public async Task<List<MyCustomClass>> FooAsync()
{
    const string cacheKey = "MyCustomClass_AllData";
    return await _cache.GetOrCreateAsync(cacheKey, async entry =>
    {
        entry.SlidingExpiration = TimeSpan.FromMinutes(30);
        // 异步查询数据库
        return await _dbContext.MyCustomClasses.ToListAsync();
    });
}

对应的异步业务方法直接用await调用即可:

public async Task<List<MyCustomClass>> MyAmazingMethodA(int targetId)
{
    var allData = await FooAsync();
    return allData.Where(item => item.Id == targetId).ToList();
}

// 如果业务中还有其他异步操作,直接结合使用
public async Task<List<DetailedDto>> MyAmazingMethodZ()
{
    var allData = await FooAsync();
    var grouped = allData.GroupBy(item => item.Category);
    
    var result = new List<DetailedDto>();
    foreach (var group in grouped)
    {
        // 调用其他异步服务处理分组数据
        var detailedDto = await _yourOtherService.ProcessGroupAsync(group);
        result.Add(detailedDto);
    }
    return result;
}

注意事项

  • IMemoryCache本身是线程安全的,GetOrCreate/GetOrCreateAsync会自动处理并发请求,避免重复执行数据库查询。
  • 根据业务需求调整缓存策略(比如绝对过期、滑动过期),确保数据时效性。
  • 如果缓存数据需要更新,记得主动移除对应缓存键,保证下次查询能获取最新数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 23:22:09