【问题标题】:Why is DBContext is disposed after putting it in IMemoryCache (.NET Core / EF Core)为什么将 DBContext 放入 IMemoryCache (.NET Core / EF Core) 后被释放
【发布时间】:2019-04-02 11:39:34
【问题描述】:

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

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

我的代码 sn-p:

    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-framework asp.net-core .net-core


    【解决方案1】:

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

    【讨论】:

    • 但是每次我需要相同的文章集时,缓存文章比调用数据库要快吗?或者可能是一个更好的例子:当我根据数据库中的一些数据创建导航时,缓存数据感觉更好,因为数据不会经常变化。
    • @CribAd 因为您需要缓存数据,而不是上下文,但前提是数据可以在应用程序的整个生命周期内安全访问(不会更改)。对于更改数据缓存,上下文会减慢速度,因为它会降低并发性。
    • 好的,事情对我来说越来越清楚了。我想把一些数据放在缓存中,我认为 _WebDbContext.Article.Include(s => s.Details); 会返回数据,但它实际上返回了一个上下文,对吧?那么如何获取缓存中的数据呢?
    • 我在答案中添加了一个更新,向您展示如何缓存数据而不是查询。
    • 非常感谢,这是我缺少的链接!
    猜你喜欢
    • 1970-01-01
    • 2022-01-24
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多