Entity Framework 4 和查询结果的缓存

Posted

技术标签:

【中文标题】Entity Framework 4 和查询结果的缓存【英文标题】:Entity Framework 4 and caching of query results 【发布时间】:2011-09-19 06:02:36 【问题描述】:

假设我有一个或 2 个表包含永远不会或很少更改的数据,那么尝试缓存这些数据有什么意义吗?或者当我第一次加载它们时,EF 上下文会为我缓存这些数据吗?我正在考虑从这些表中加载所有数据并使用静态列表或其他东西将这些数据保存在内存中,并在我需要相同上下文中的数据时查询内存中的数据而不是表。我所说的那些表通常包含几百行数据。

【问题讨论】:

【参考方案1】:

EF 上下文将缓存“每个实例”。也就是说,DbContext 的每个实例都保留自己独立的对象缓存。您可以将生成的对象列表存储在静态列表中,然后随意查询,而无需返回数据库。为了安全起见,请确保您在执行查询之后放弃DbContext

var dbContext = new YourDbContext();
StaticData.CachedListOfThings = dbContext.ListOfThings.ToList();

您可以稍后使用 LINQ 查询静态列表。

var widgets = StaticData.CachedListOfThing.Where(thing => thing.Widget == "Foo");

查询执行内存中的集合,而不是数据库。

【讨论】:

我可以直接在缓存集合中添加结果列表吗?我的意思是 HttpRuntime.Cache["MyKey"] = context.ListOfThings.ToList() @ed-chapel 我不知道为什么这是一个好主意,在更多情况下,我们想要缓存的数据很少更改(但它仍然会更改)。发生变化时使用您的建议无济于事,还是我遗漏了什么? @K-SaMa 你是对的,这对刷新数据没有任何作用。正如 OP 所要求的那样,该解决方案仅防止如何防止重复调用。检测和更新缓存是不同的更难的问题,这里不问。【参考方案2】:

您可以查看EF caching provider,但请注意,这种方式的缓存是严格基于查询执行的——因此您必须始终使用相同的查询来获取缓存数据。如果您使用另一个查询,它将首先被执行以被视为缓存,然后您再次使用它来命中缓存。如果您想避免这种情况并缓存数据并能够在缓存集合上运行任何查询,您必须使用您自己的解决方案(只需将数据加载到列表并将其保存在某处)。当您将实体加载到缓存列表时,请确保关闭代理创建(延迟加载和更改跟踪)。

缓存每个上下文实例确实有效,但使用上下文本身作为缓存是非常糟糕的选择 - 在大多数情况下,我将其称为 EF 反模式。 Use context as unit of work = 不要为多个逻辑操作重用上下文。

【讨论】:

【参考方案3】:

对于任何 ef4 linq 查询,您必须自己滚动,因为它们总是被解析为 sql,因此总是会命中 db。为您的几个表创建一个简单的缓存可能并不难编写。

如果你要通过 id 查询,你可以使用ObjectContext.GetObjectByKey method,它会在查询数据库之前先在对象缓存中查找。

【讨论】:

小心,“linq 总是解析为 sql”是很不真实的。 LinqToObjects 是与 SQL 或一般数据库无关的几个提供程序之一。 视情况而定。如果用户包含ToArray()ToList() 或以其他方式强制对数据库执行查询,则后续表达式通常不是LinqToEF。你的“总是”太绝对了。 @ed,这是绝对的。它们有时不会被解析为 sql,它们总是如此。如果有人评估查询,他们必须开始一个新的查询,然后它就不是同一个查询......这不是真正的辩论,它只是简单的事实。来自msdn.microsoft.com/en-us/library/bb896241.aspx “当您查询概念模型时,实体框架将基于概念模型的 LINQ to Entities 和 Entity SQL 查询转换为针对数据源的等效查询。”对我来说似乎很绝对。 @ed,我认为你错过了这里的核心点。当然,当您查询 list 时,它不会命中数据库。没有要命中的数据库。当您查询对象上下文时。 很公平。看起来我们好像在互相交谈。如果有人读到这里,请务必接受 Nathan 关于避免使用数据库的警告。

以上是关于Entity Framework 4 和查询结果的缓存的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 4.1 DbContext API 中的接口和存储库抽象中断子查询?

用于简单数据模型和多对多关系的 Optimal Entity Framework 4 查询

使用 Entity Framework 4 和 Linq 查询比较 DateTime 属性中的日期的简单方法

Entity Framework 4.1 两个跟踪查询

Entity Framework 4 中的 Linq 查询。糟糕的性能

用Entity Framework 连表查询