持久化实体框架查询缓存

Posted

技术标签:

【中文标题】持久化实体框架查询缓存【英文标题】:Persist Entity Framework query cache 【发布时间】:2014-11-22 06:32:53 【问题描述】:

我有一个 ASP.NET MVC 5 Web 应用程序并使用 EF 6.1 访问我的数据库。 我有一些相当复杂的 LINQ 查询,编译时间长达 10 秒,然后在几毫秒内执行。 EF 确实很好地缓存了这个查询,并且第二次执行查询时它会在这几毫秒内返回。 但是这个缓存不会持久化,所以每次应用重启时都需要重新编译查询,这又需要 10 秒。

有没有办法持久化这个查询缓存,让它在应用重启后仍然存在?

【问题讨论】:

fusonic.net/en/blog/2014/07/09/… 感谢您的链接,但我已经完成了大部分工作,它不处理查询缓存,而只处理模型缓存... 查询缓存是QueryCacheManager里面的一个Dictionary。我尝试使用反射保存它,但由于 QueryCacheKey 和 QueryCacheEntry 不是公共的并且没有标记为可序列化,所以这是不可能的。保存/加载查询计划缓存将是一个非常有用的功能,因此您应该在 entityframework.codeplex.com/workitem/list/advanced 上创建一个问题 @bmurmistro:我上个月在 /build/ 与 EF 团队的 Rowan Miller 进行了交谈,使用 EF 7 这将很容易实现或已经“在盒子里”,所以我正在等待 EF 7 ... 太棒了!感谢@ChrFin 的更新 【参考方案1】:

您可以使用编译查询:see here 或 here

static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 = 
CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>(
        (ctx, total) => from order in ctx.SalesOrderHeaders
                        where order.TotalDue >= total
                        select order);

但是正如here 提到的,查询对象不能超出范围。您可以通过将其缓存在会话中或作为应用程序变量来处理此问题。

【讨论】:

对不起,但这没有帮助,因为在我的应用程序执行期间,它们已经被 EF 缓存了。我想持久地存储它,这样它就可以在应用重新启动后继续存在... 您可以在应用程序启动时在后台编译它,以便在您使用它时准备好。如果这不可能,您可以将编译的查询对象序列化到文件并从那里恢复它。因此,只有第一次使用很慢。然而,这只能通过编译查询来完成。

以上是关于持久化实体框架查询缓存的主要内容,如果未能解决你的问题,请参考以下文章

JAVAEE学习笔记hibernate02:实体规则对象状态缓存事务批量查询和实现客户列表显示

Hibernate 二级缓存疑难点

学说 2 和 ORM:如何缓存某个实体的每个查询?

Hibernate缓存

mybatis缓存机制

ruh使用MyBatis缓存