无法访问已释放的对象,使用MemoryCache

5
我收到了这个信息:
System.ObjectDisposedException: 无法访问已处理的对象。造成此错误的一个常见原因是处理从依赖注入解析的上下文,然后稍后尝试在应用程序的其他位置使用相同的上下文实例。如果您正在调用Dispose()方法释放上下文或将上下文包装在using语句中,则可能会发生此情况。如果使用依赖注入,请让依赖注入容器处理上下文实例的释放。
控制器:
    [HttpGet]
    public IActionResult GetAllTags()
    {
        try
        {
            return Ok(GetAll());
        }
        catch(Exception ex)
        {
            return ControllerHelper.LogAndReturnBadRequest(_logger, ex);
        }
    }

    private IEnumerable<TagDto> GetAll()
    {
            IEnumerable<TagDto> tags;
            if (!_cache.TryGetValue(CacheKeys.States, out tags))
            {
                tags = _service.GetAll()?.Select(t => _mapper.Map<TagDto>(t));

                if(tags != null)
                    _cache.Set(CacheKeys.States, tags);
            }

            return tags;
    }

Startup.cs

services.AddMemoryCache();

我一行一行地调试代码,但即使在我的代码的最后一行之后,都没有任何错误。

我看到的错误是在 Kestrel 控制台中。值得注意的是,只有在从 _cache 获取标记时才会出现错误,而第一次直接从数据库获取标记时不会出现。

enter image description here

这是我从 Postman 请求中得到的:

enter image description here

有很多类似的问题涉及 dispose 对象,但在这里您可以看到我在代码中没有使用 dispose () 或 using()。


你在哪一行代码上遇到了这个错误? - Ron Beyer
@RonBeyer 我正在逐行调试它,但即使在返回Ok(GetAll())之后也没有发生任何异常。我将更新我的帖子,包括Postman中的响应和Kestrel控制台中的错误。 - Franva
@Franva - 你能解决这个问题吗?我也遇到了完全相同的问题。我尝试使用ToList(),但仍然没有运气。我的Db上下文依赖是瞬态的,并且在服务层中作为作用域注入。我注意到切换到单例实例会消除此错误;但那不是我想要的。 - Saket
1
工作 - 我从数据库中得到的结果集有多个'IEnumerable'属性 - 我必须对每个属性调用ToList进行显式评估。 - Saket
仅供参考,相关链接:https://dev59.com/GK_la4cB1Zd3GeqPs3Bq - crazyTech
显示剩余3条评论
1个回答

2
我的猜测是,您需要在将查询结果存储到缓存之前对其进行水合处理。 Linq使用延迟执行,这意味着底层源不会实际查询,直到尝试枚举结果。因此,您只是在缓存中存储一个查询,并且在尝试检索实际数据时,底层上下文已被处理。
在查询中添加ToList并将列表存储在缓存中:
tags = _service.GetAll()?.Select(t => _mapper.Map<TagDto>(t)).ToList();

我还要指出的是,返回序列的linq查询结果永远不会为null。它可能是的,因此如果您不想缓存一个空结果,可以将您的null检查更改为if (tags.Any())

仅供参考,相关链接如下:https://dev59.com/GK_la4cB1Zd3GeqPs3Bq - crazyTech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接