EF 4.3使用本地缓存而不是从数据库重新获取
有人可以向我解释为什么我的EF(4.3)代码首先下面的代码导致“旧”密码被检索。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"
}
密码是“oldpassword”开始。所以我在另一个上下文(context2)中更改密码,然后再次将其提取到user2中。我可以验证两者的输出是“oldpassword”。从分析SQL,我可以看到密码确实发生了变化,我还可以看到填充到数据库的代码,但它只是不使用这些值。
据我所知,英孚已经在本地上下文缓存和跟踪实体的方法的概念,但是从我的理解,一个context.Installers.Where(..)
应该强制从数据库中重新读取,而context.Installers.Find()
应该看看当地的情况。看来,无论我如何查询安装程序,它都使用本地缓存。
EDIT
由于@Reinard的溶液。我被误解的文档 - 我从here阅读:
注意DbSet和IDbSet始终对数据库 创建查询和总会涉及往返于即使 实体已经返回数据库中存在的背景下, 。
所以我认为,因为它会去数据库,它会重新获取我的对象。究竟发生了什么,它到了数据库,取得了对象,发现我已经在跟踪那个对象(因为之前的负载),所以我最终得到了旧对象 - 这实际上是文档说的!
使用context.Installers.Local.Clear()
没什么区别奇怪的是,我需要AsNoTracking().
无论Where
或Find
将明确地从数据库中重新提取。据我所知Find只有在上下文中不存在的情况下才会从数据库中检索实体。
为了明确强制使用AsNoTracking()重新读取。
例如
context.Installers.AsNoTracking().Where(u => u.UserName == "admin").FirstOrDefault();
辉煌 - 我明白现在发生了什么:)我是错误的文件,谢谢你 - 我会编辑我的问题来详细说明 – 2012-07-09 12:02:19
非常好,我只是寻找这非常同样的答案,因为我需要获取原始的完整obj图,因为它在数据库中并将其与其他修改的实例进行比较 – 2013-07-22 00:35:42
你确定你正在比较相同的记录吗?在第一个上下文中,您正在使用.Where(...)。FirstOrDefault()和第二个上下文中使用.Single(...)。生成的SQL是否相同? – Maarten 2012-07-09 10:29:35
我不能重现描述的行为,并同意whit @Maarten – tschmit007 2012-07-09 10:37:13
绝对100%肯定 - 唯一不同的Linq表达式与我用来更新DB中的记录的第二个上下文,所以它并不重要这个Linq很不同。分析器验证正确的记录得到更新 – 2012-07-09 11:57:57