C# 实体框架4和查询结果的缓存

C# 实体框架4和查询结果的缓存,c#,caching,entity-framework-4,C#,Caching,Entity Framework 4,假设我有一个表或2,其中包含永远不会更改或很少更改的数据,是否有必要尝试缓存这些数据?或者,当我第一次加载这些数据时,EF上下文会为我缓存这些数据吗?我正在考虑从这些表中加载所有数据,并使用静态列表或其他方法将这些数据保存在内存中,并在需要相同上下文中的数据时查询内存中的数据而不是表。我所说的那些表通常包含几百行数据。对于任何ef4 linq查询,您都必须滚动自己的表,因为它们总是解析为sql,因此总是会命中数据库。为两个表编写一个简单的缓存可能并不难 但是,如果要按id进行查询,可以使用,它将

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

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

但是,如果要按id进行查询,可以使用,它将在查询db之前查看对象缓存。

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

var dbContext = new YourDbContext();
StaticData.CachedListOfThings = dbContext.ListOfThings.ToList();
稍后可以使用LINQ查询静态列表

var widgets = StaticData.CachedListOfThing.Where(thing => thing.Widget == "Foo");
查询执行的是内存中的集合,而不是数据库。

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


每个上下文实例的缓存确实有效,但使用上下文本身作为缓存是一个非常糟糕的选择-在大多数情况下,我称之为EF反模式不要为多个逻辑操作重用上下文

小心,“linq总是解析为sql”是非常不真实的。LinqToObjects是与SQL或数据库无关的几个提供程序之一。具体取决于。如果用户包含一个
ToArray()
ToList()
或以其他方式强制对数据库执行查询,则后续表达式通常不LinqToEF。你的陈述用“总是”太绝对了。@ed,这是绝对的。它们有时不会解析为sql,但总是这样。如果有人对查询求值,他们必须开始一个新的查询,然后它就不是同一个查询了。。。这不是一场真正的辩论,只是简单的事实。从“当您查询概念模型时,实体框架将LINQ转换为实体,并将基于概念模型的实体SQL查询转换为针对数据源的等效查询”开始,我觉得这是非常绝对的。@ed,我认为您缺少这里的核心点。当然,当你查询一个列表时,它不会命中数据库。没有可命中的数据库。当你查询一个对象的上下文时,这就足够了。看起来我们好像是在互相推诿。如果有人读到这里,请接受Nathan关于避免使用数据库的警告。我可以直接在缓存集合中添加结果列表吗?我的意思是HttpRuntime.Cache[“MyKey”]=context.ListOfThings.ToList()@ed。我不知道为什么这是一个好主意,在更多的情况下,我们想要缓存的数据很少发生更改(但仍然会更改)。当发生更改时,使用您的建议不会有帮助,或者我遗漏了什么吗?@K-SaMa您是对的,这对刷新数据没有任何作用。正如OP询问的那样,这个解决方案只是防止了如何防止重复呼叫。检测和更新缓存是不同的更难的问题,这里不要求。