2013-12-12 35 views
2

我正在使用实体框架5.0和SQLite数据库。我有一个场景,我对数据库记录进行了修改,然后使用同一个表的实体对象的新实例来读取相同的记录,但是我得到了旧的值。在调试的时候,如果我去我的数据库工具并查看记录,这些变化就在那里,但是EF并没有选择它们。它会在晚些时候拿起它们,但我无法确定它是什么时候。实体框架在SaveChanges获取旧值后读取

以下是代码片段。首先,我执行使用更新的SaveChanges():

tblTest efTestTbl = context.tblTests.Find(recID); 
context.tblTests.Attach(efTestTbl); 
efTestTbl.Value1 = "newValue"; // This changed it from "oldValue" :-) 
int changedRecs = context.SaveChanges(); 

这上面的代码似乎总是工作并保存更改数据库。 changedRecs最终等于1.我可以在代码中的这一点之后休息,并使用我的数据库工具查看数据库中的值,并且该列将等于“newValue”。

现在,如果我执行下面的读,用不同的表对象上一次更新后直接,但相同的实例的上下文对象:

tblTest efTestTbl = context.tblTests.Find(recID); 

在efTestTbl.Value1的价值将等于“属性oldValue” 。我看到一些关于EF没有缓存任何东西的评论,但我不能相信这是真的。在另一个论坛上,我看到一场谈话谈论关于ObjectQuery的MergeOption,缓存被称为“身份解析”。这是内容丰富的,但没有帮助我,因为我没有使用查询和“ExecuteNonQuery()”方法。

我的方案需要我写出一个更改,然后从数据库读取并记录更改作为验证步骤。

任何帮助,你可以给我找到一种方法来刷新缓存将不胜感激。

+0

在代码中使用相同的上下文实例吗? –

回答

1

根据上下文中发生的情况,您尝试加载的对象可能已经存在于其他上下文中。

这就是我之前解决这个问题的方法;

public static class ZarettoContextExtensionClass 
{ 
    public static tblTest Reload(this tblTest item, DbContext c) 
    { 
     c.Configuration.AutoDetectChangesEnabled = false; 
     c.Entry(item).Reload(); 
     c.Configuration.AutoDetectChangesEnabled = true; 
     return item; 
    } 
} 

那么很明显,你会怎么做:

efTestTbl.Reload(context) 
+0

你不是这个意思:public static tblTest Reload(this tblTest item,DbContext c)?? –

+0

@RobertAchmann是的,编辑 –

0

如果使用

tblTest efTestTbl = context.tblTests.FirstOrDefault(t => t.Id == recID); 

,而不是

tblTest efTestTbl = context.tblTests.Find(recID); 

你可以肯定的是EF会查询数据库,你会得到持久的数据。

使用Find()方法EF将首先检查对象是否已经在您的数据库上下文中,然后才决定是否会查询数据库。

这并不回答问题,为什么你会得到旧的数据,但应该解决你的问题。

我只是想知道为什么你在已经连接的实体efTestTbl上使用.Attach()方法? 在我看来,你分离()它在某些时候,执行没有跟踪的变化,并附有不正确的值(不同于数据库),这是后来幸运的巧合保存。

你还使用AutoDetectChanges吗?