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

ASP.NET Core MVC内存缓存IQueryable数据遇ObjectDisposedException求助

ASP.NET Core MVC内存缓存报错ObjectDisposedException的解决

报错原因

你缓存了IQueryable<v_ListView>对象,但IQueryable是延迟执行的查询表达式,它并没有实际从数据库获取数据,只是保留了对DbContext的引用。ASP.NET Core中DbContext默认是Scoped生命周期,请求结束后会被自动释放。当后续请求使用缓存的IQueryable时,DbContext已经被销毁,就会抛出ObjectDisposedException。

另外你原代码还有一个隐藏问题:所有Where过滤都没有生效——因为IQueryable是不可变的,Where方法会返回一个新的查询实例,你必须把结果重新赋值给变量,否则原来的CompanyList不会应用任何过滤逻辑。

修复步骤

1. 缓存实际数据集合而非IQueryable

把缓存对象从IQueryable改成List<v_ListView>,这样在缓存时就执行数据库查询,得到内存中的数据集合,不再依赖DbContext。

2. 修正过滤逻辑的赋值问题

所有Where的结果必须重新赋值给变量,确保过滤逻辑生效。

修复后的完整代码

public async Task<(List<v_ListView>, int TotalCount)> GetList(ListDatatableParam param)
{    
    string cacheKey = "ListViewKey";
    List<v_ListView> cachedList;
    
    // 尝试获取全量数据缓存
    if (!_memoryCache.TryGetValue(cacheKey, out cachedList))
    {
       // 执行数据库查询,获取全量数据并存入缓存
       cachedList = await _Context.v_ListView.ToListAsync();
       _memoryCache.Set(cacheKey, cachedList,
           new MemoryCacheEntryOptions()
           .SetAbsoluteExpiration(TimeSpan.FromSeconds(60)));
    }

    // 基于缓存的内存集合进行过滤
    var filteredList = cachedList.AsQueryable()
        .Where(p => 
            string.IsNullOrEmpty(SearchTerm) ||
            (!string.IsNullOrEmpty(p.name) && SearchTerm.Length <= p.name.Length && p.name.ToLower().Contains(SearchTerm)) ||
            (!string.IsNullOrEmpty(p.CompanyNumber.ToString()) && p.CompanyNumber.ToString().ToLower().Contains(SearchTerm))
        );

    if (!filterStatus.Contains("All") && filterStatus[0] != null)
    {
        filteredList = filteredList.Where(x => filterStatus.Contains(x.Status));
    }

    if (filterRegion[0] != null)
    {
        if (filterRegion.Contains("No Region"))
        {
            filteredList = filteredList.Where(x => x.Region == null || x.Region.Equals(string.Empty));
        }
        else
        {
            filteredList = filteredList.Where(x => filterRegion.Contains(x.Region));
        }
    }

    int totalCount = filteredList.Count();
    var paginatedList = filteredList.Skip(param.iDisplayStart).Take(param.iDisplayLength).ToList();

    return (paginatedList, totalCount);
}

进阶优化(针对大数据量场景)

如果v_ListView数据量很大,全量缓存会占用过多内存,建议根据查询参数生成唯一缓存Key,缓存过滤后的结果:

// 组合所有查询参数生成唯一缓存Key,避免不同查询共用缓存
string cacheKey = $"ListView_{SearchTerm}_{string.Join("|", filterStatus)}_{string.Join("|", filterRegion)}_{param.iDisplayStart}_{param.iDisplayLength}";

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:04:55