c# - 为什么将 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 在我第一次将其放入缓存后被释放。我该如何处理?
解决方案
您正在使用依赖注入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
。
推荐阅读
- aws-lambda - 有人在使用无服务器部署 lambda 函数时遇到问题吗?
- android - 自定义微调器以获得不同的外观
- r - 如何使用 quosure 在 dplyr 中将过滤器语句作为函数参数传递
- node.js - 如何让浏览器显示 pdf 文件而不是从 Nodejs 服务器下载?
- android - Xamarin forms webview takes all the screen height
- java - WAP 输入一个句子并打印该句子中出现了多少次“is”[Java]
- java - Java 和 Kotlin 中的 Lambda 之间的差异
- awk - gensub() 可以接受函数调用作为第二个参数吗?
- ruby-on-rails - Mongo::Error::SocketError:在 mongo 副本集中执行查询时管道损坏
- laravel - Laravel 多重身份验证来自两个不同的路由和视图