EF 4.3使用本地缓存而不是从数据库重新获取

Mat*_*rts 1 .net c# entity-framework ef-code-first

有人可以向我解释为什么我的EF(4.3)代码首先代码导致检索到"旧"密码.

using (var context = new CableSenseInstanceConfiguratorContext())
{
    var user = context.Installers.Where(u => u.UserName == "admin").FirstOrDefault();
    Console.WriteLine(user.Password); // Outputs "oldpassword"

    // Change the details on a different context;
    using (var context2 = new CableSenseInstanceConfiguratorContext())
    {
        var installer = context2.Installers.Single(i => i.UserName == "admin");
        installer.Password = "changed"; 
        context2.SaveChanges();
    }

    var user2 = context.Installers.Where(u => u.UserName == "admin").FirstOrDefault();
    Console.WriteLine(user2.Password); // Outputs "oldpassword"
}
Run Code Online (Sandbox Code Playgroud)

密码是"oldpassword"开始.所以我在另一个上下文(context2)中更改密码,然后再次将其提取到user2中.我可以验证两者的输出都是"oldpassword".从剖析在SQL,我可以看到密码不得到改变,我还可以看到用于填充user2的代码IS去到数据库中,但它只是不使用这些值.

我理解EF将Local上下文的概念作为缓存和跟踪实体的一种方式,但据我所知,a context.Installers.Where(..)应该强制从数据库中重新获取,而a context.Installers.Find()应该在本地上下文中查看.似乎无论我如何查询安装程序,它都使用本地缓存.

编辑

感谢@Reinard提供的解决方案.我误解了文档 - 我从这里读到:

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

所以我假设因为它会进入数据库,它会重新获取我的对象.实际发生的是它进入数据库,获取对象,发现我已经在跟踪该对象(因为之前的加载),所以我最终得到了旧对象 - 这实际上是文档所说的!

使用context.Installers.Local.Clear()毫无意义,我需要AsNoTracking().

Rei*_*las 5

既不会WhereFind不会明确地从数据库中重新提取.据我所知,只有在上下文中不存在实体时,Find才会从数据库中检索实体.

为了明确强制重新使用AsNoTracking().

例如

context.Installers.AsNoTracking().Where(u => u.UserName == "admin").FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)