首页 > 解决方案 > 为什么将 DBContext 放入 IMemoryCache (.NET Core / EF Core) 后被释放

问题描述

我正在尝试将 db-data 的子集放入 IMemoryCache 中,但是第二次调用该应用程序时,出现错误:

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

我的代码片段:

    public class ArticleRepository : IArticleRepository
    {
        private readonly WebDbContext _WebDbContext;
        private readonly IMemoryCache _cache;

        public ArticleRepository(WebDbContext WebDbContext, IMemoryCache cache)
        {
            _WebDbContext = WebDbContext;
            _cache = cache;
        }

        public IQueryable<Articles> WebshopArticles
        {
            get
            {
                return _cache.GetOrCreate("WebshopArticles", entry =>
                {
                    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
                    return _WebDbContext.Article.Include(s => s.Details);
                });                
            }
        } 

        public IQueryable<Articles> GetArticles(string category)
        {
            return WebshopArticles.FirstOrDefault(s => s.Category == Category);
        }
    }

看起来 DBContext 在我第一次将其放入缓存后被释放。我该如何处理?

标签: c#entity-frameworkasp.net-core.net-core

解决方案


您正在使用依赖注入WebDbContext通过构造函数获取您的实例。ASP.NET Core 通过WebDbContext为您初始化一个对象并在创建存储库类的实例时将其注入构造函数调用来实现此目的。

但该WebDbContext对象仅在当前 HTTP 请求的生命周期内可用。一旦该 HTTP 请求完成,ASP.NET Core 就会摆脱它。这就是为什么你看到它被处理掉了。

更新:我明白你在做什么。问题在这里:

return _WebDbContext.Article.Include(s => s.Details);

那不会缓存数据。这会缓存查询 ( IQueryable)。在您枚举它(循环通过它)之前,查询不会被执行。这被称为“延迟加载”。因此,您GetArticles实际上每次调用时都会再次执行查询。

第一次使用它时(在缓存的同一个 HTTP 请求中),它就可以工作。但是当你第二次使用它时,上下文被释放并且无法执行查询。

您需要强制它立即执行查询。一个简单的方法是调用ToList()

return _WebDbContext.Article.Include(s => s.Details).ToList();

您还需要将属性类型更改为IEnumerable


推荐阅读