为什么将DBContext放入IMemoryCache(.NET Core / EF Core)后会被丢弃

时间:2018-10-29 14:03:02

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

我试图将一部分db数据放入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放入高速缓存后,它似乎已被处置。我该如何处理?

1 个答案:

答案 0 :(得分:10)

您正在使用依赖项注入通过构造函数获取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