为什么Entity Framework 6.x没有缓存结果?

Ada*_*lin 39 c# caching entity-framework entity-framework-6

也许我误解的缓存是DbContextDbSet做,但我的印象是,有一些高速缓存,将继续下去.当我运行以下代码时,我看到了我不会期望的行为:

var ctx = CreateAContext();
var sampleEntityId = ctx.SampleEntities.Select(i => i.Id)
                                       .Single(i => i == 3); //Calls DB as expected
var cachedEntityId = ctx.SampleEntities.Select(i => i.Id)
                                       .Single(i => i == 3); //Calls DB unexpectedly
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?我认为你得到的部分原因DbSet是它首先检查本地缓存,以便在查询数据库之前查看该对象是否存在.我在这里缺少某种配置选项吗?

dan*_*wig 42

什么@ emcas88想说的是,当你使用EF只会检查缓存.Find的方法DbSet.

使用.Single,.First,.Where等不会,除非你使用的二级缓存缓存的结果.

  • 您是否知道在EF6中实施二级缓存的任何资源或已经完成的任何项目? (3认同)
  • @mjalil我认为你将结果缓存与元数据,视图和物化器缓存混淆.只有`.Find`会将实际查询结果缓存在第一级缓存中. (3认同)
  • 由于[实体框架4,5和6的性能考虑],EF**将CACHE**".First"的结果(https://msdn.microsoft.com/en-us/data/hh949853.aspx# 2).热查询使用缓存数据.我还有一个使用`.Where`的代码,它从缓存中读取.可能的EF也会缓存`.Single` (2认同)

emc*_*s88 29

这是因为执行了extensor方法,使用了上下文的Find方法

contextName.YourTableName.Find()
Run Code Online (Sandbox Code Playgroud)

首先验证缓存.希望能帮助到你.

  • +1,这实际上是正确的答案.我不认为不完美的英语应该是一个downvote的理由. (14认同)
  • 我不太清楚你的意思. (2认同)

cry*_*yss 23

有时我使用我的扩展方法:

using System.Linq;
using System.Linq.Expressions;

namespace System.Data.Entity
{
    public static class DbSetExtensions
    {
        public static TEntity FirstOrDefaultCache<TEntity>(this DbSet<TEntity> queryable, Expression<Func<TEntity, bool>> condition) 
            where TEntity : class
        {
            return queryable
                .Local.FirstOrDefault(condition.Compile()) // find in local cache
                   ?? queryable.FirstOrDefault(condition); // if local cache returns null check the db
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

db.Invoices.FirstOrDefaultCache(x => x.CustomerName == "Some name");
Run Code Online (Sandbox Code Playgroud)

您也可以使用SingleOrDetfault替换FirstOrDefault.

  • 我喜欢这个解决方案.只是一点点反馈:你在"DbSet <TEntity> queryable"之前错过了"this",并且知道"Where(condition).FirstOrDefault()"与".FirstOrDefault(condition)"相同.谢谢分享哭泣. (3认同)

Vla*_*nko 11

看看EF Docs,你会在那里找到答案:

请注意,DbSet和IDbSet始终针对数据库创建查询,并且即使返回的实体已存在于上下文中,也将始终涉及到数据库的往返.在以下情况下对数据库执行查询:

  • 它由foreach(C#)或For Each(Visual Basic)语句枚举.
  • 它是由一家集经营列举如ToArray,ToDictionaryToList.
  • LINQ运算符例如FirstAny在查询的最外部指定.
  • 下面的方法被称为:在Load上一个扩展方法DbSet,DbEntityEntry.ReloadDatabase.ExecuteSqlCommand.


Dav*_*ave 7

EF6不会执行缓存ootb的结果.要缓存结果,您需要使用二级缓存.在CodePlex上看到这个有前景的项目:

EF 6.1的二级缓存

请记住,如果数据库中的数据发生更改,您将无法立即了解它.有时这取决于项目很重要.;)

  • 你在谈论*二级*缓存.我相信,他所要求的是*一级*缓存.:) (4认同)