【问题标题】:Cannot access a disposed object with MemoryCache无法使用 MemoryCache 访问已处置的对象
【发布时间】:2019-09-20 11:59:11
【问题描述】:

我收到这条消息:

System.ObjectDisposedException:无法访问已处置的对象。一种 此错误的常见原因是处理已解决的上下文 从依赖注入,然后尝试使用相同的 应用程序中其他地方的上下文实例。如果您可能会发生这种情况 在上下文上调用 Dispose(),或者将上下文包装在 使用语句。如果你使用依赖注入,你应该让 依赖注入容器负责处理上下文 实例。

控制器:

    [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中获取标签时发生,而不是在第一次直接从数据库中获取标签时发生。

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

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

【问题讨论】:

  • 你在哪一行得到这个错误?
  • @RonBeyer 我正在逐行调试它,但即使在 return Ok(GetAll());没有例外。我将更新我的帖子以包含 Postman 中的响应和 Kestrel 控制台中的错误。
  • @RonBeyer 我从 Kestrel 控制台更新了错误并附上了邮递员的回复
  • 似乎您的 DbContext 已被处置。
  • 作品 - 我的数据库结果集有多个 'IEnumerable' 属性 - 我必须在每个属性上调用 ToList 以进行显式评估。

标签: c# asp.net-core entity-framework-core


【解决方案1】:

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

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

tags = _service.GetAll()?.Select(t => _mapper.Map<TagDto>(t)).ToList();

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

【讨论】:

    猜你喜欢
    • 2011-10-23
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多