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

Fra*_*nva 5 c# entity-framework-core asp.net-core

我收到此消息:

System.ObjectDisposeException:无法访问已处置的对象。导致此错误的一个常见原因是处置从依赖项注入解析的上下文,然后尝试在应用程序的其他位置使用相同的上下文实例。如果您在上下文上调用 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;
    }
Run Code Online (Sandbox Code Playgroud)

启动.cs

services.AddMemoryCache();

我正在逐行调试代码,但即使在代码的最后一行之后,也根本没有错误。

我看到的错误是在 Kestrel 控制台中。值得注意的是,该错误仅在从 _cache 获取标签时发生,而在第一次直接从数据库获取标签时不会发生。

在此输入图像描述

这是我从邮递员请求中得到的信息:

在此输入图像描述

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

D S*_*ley 2

我的猜测是,您需要在将查询结果存储在缓存中之前对查询结果进行水化。Linq 使用延迟执行,这意味着在您尝试枚举结果之前不会真正查询底层源。因此,您只需将查询存储在缓存中,当您尝试检索实际数据时,底层上下文就已被释放。

添加ToList到您的查询并将列表存储在缓存中:

tags = _service.GetAll()?.Select(t => _mapper.Map<TagDto>(t)).ToList();
Run Code Online (Sandbox Code Playgroud)

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