在SaveChanges获取旧值后读取实体框架

时间:2013-12-12 06:05:52

标签: c# entity-framework sqlite

我正在使用Entity Framework 5.0和SQLite数据库。我有一个场景,我修改了数据库记录,然后我使用同一个表的实体对象的新实例来读取相同的记录,但我得到旧的值。在调试时,如果我转到我的数据库工具并查看记录,那么更改就在那里,但是EF并没有提到它们。它会在以后最终获取它们,但我无法确定它是什么时候。

以下是代码段。首先,我使用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()”方法。

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

您可以帮助我找到一种刷新缓存的方法。

3 个答案:

答案 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)

答案 1 :(得分:0)

如果您使用

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

而不是

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

您可以确定EF将查询数据库并获得持久数据。

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

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

我只是想知道你为什么在已经附加的实体efTestTbl上使用.Attach()方法? 在我看来,你在某个时候分离了()它,执行了未被跟踪的更改,并使用不正确的值(不同于数据库)来接收它,之后只是幸运的巧合保存了它。

您还在使用AutoDetectChanges吗?

答案 2 :(得分:0)

我在要查询的表上使用AsNoTracking()函数来解决此问题。在您的情况下,查询将如下所示。

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