简体   繁体   English

无法使用MemoryCache访问已处置的对象

[英]Cannot access a disposed object with MemoryCache

I am getting this message: 我收到此消息:

System.ObjectDisposedException: Cannot access a disposed object. System.ObjectDisposedException:无法访问已处置的对象。 A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. 导致此错误的常见原因是,处理从依赖项注入中解决的上下文,然后稍后尝试在应用程序中的其他位置使用相同的上下文实例。 This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. 如果在上下文上调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。 If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. 如果使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。

Controller: 控制器:

    [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 Startup.cs

services.AddMemoryCache();

I was debugging the code line by line, but even after the last line of my code, there is no error at all. 我正在逐行调试代码,但是即使在代码的最后一行之后,也没有任何错误。

The error I saw was in Kestrel console. 我看到的错误是在Kestrel控制台中。 Worth to notice, the error only happen when fetching tags from the _cache, not happen on the first time when tags fetched directly from database. 值得注意的是,该错误仅在从_cache获取标签时发生,而不是在第一次直接从数据库中获取标签时发生。

在此处输入图片说明

Here is what I got from Postman request: 这是我从邮递员的要求中得到的:

在此处输入图片说明

Many similar questions referring to dispose objects, but here you can see that I do not have dispose(), or using() in my code. 许多类似的问题涉及到处理对象,但是在这里您可以看到我的代码中没有dispose()或using()。

My guess is you need to hydrate the results of your query before storing in in the cache. 我的猜测是,在存储在缓存中之前,需要先对查询结果进行混合处理。 Linq uses deferred execution , which means that the underlying source won't actually be queried until you try to enumerate the results. Linq使用延迟执行 ,这意味着在尝试枚举结果之前,实际上不会查询基础源。 So you are just storing a query in the cache, and by the time you try to retrieve the actual data, the underlying context is disposed. 因此,您只是将查询存储在缓存中,并且当您尝试检索实际数据时,基础上下文已被处置。

Add a ToList to your query and store the list in the cache: ToList添加到查询中,并将列表存储在缓存中:

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

I would also note that the result of a linq query that returns a sequence will never be null. 我还要注意,返回序列的linq查询的结果永远不会为空。 It might be empty , so if you don't want to cache an empty result you could change your null check to if (tags.Any()) . 它可能为 ,因此如果您不想缓存空结果,则可以将null检查更改为if (tags.Any())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM