【问题标题】:EntityFramework 6: How do I find a previously found record?EntityFramework 6:如何找到以前找到的记录?
【发布时间】:2016-07-27 20:05:34
【问题描述】:

如果我在 EntityFramework 6 (ADO) 中找到一条记录,然后再次尝试查找该记录,则 Find 方法返回 0。这是一个示例:

var db3 = new IMS();

db3.TabModuleSettings.Find(973, "ShowSoldOut"); //Local.Count=1
db3.TabModuleSettings.Local.Clear(); //Local.Count=0

db3.TabModuleSettings.Find( 142, "AllowIndex" ); //Local.Count=1
db3.TabModuleSettings.Local.Clear(); //Local.Count=0

db3.TabModuleSettings.Find(973, "ShowSoldOut"); //Local.Count=0
db3.TabModuleSettings.Local.Clear(); //Local.Count=0

db3.TabModuleSettings.Find( 142, "AllowIndex" ); //Local.Count=0

如何找到以前找到的记录?

【问题讨论】:

    标签: c# entity-framework ado.net find entity-framework-6


    【解决方案1】:

    要记住两件事:

    • 如果您执行Local.Clear(),则Local 集合中的实体将被标记为删除。所以键值为(973, "ShowSoldOut") 的实体仍然存在于上下文的缓存中,但它的状态是Deleted。 (与(142, "AllowIndex") 相同,稍后)。

    • DbSet.Find 首先在上下文的缓存中查找实体,然后在找不到时在数据库中查找。如果实体在缓存中找到,但被删除,EF 认为它不应该再存在并且它不会返回它。

    我不知道你为什么要打这些Local.Clear() 电话,但我希望你现在意识到这是要小心使用的声明。

    清除缓存的正确方法是分离实体,例如一个 Local 集合:

    foreach (var x in db3.TabModuleSettings.Local.ToList())
    {
        Entry(x).State = System.Data.Entity.EntityState.Detached;
    }
    

    (尽管这不会分离已删除的实体)。

    或者整个缓存:

    foreach (var entry in db3.ChangeTracker.Entries())
    {
        entry.State = System.Data.Entity.EntityState.Detached;
    }
    

    (也会分离已删除的实体)。

    或特定类型的所有实体(包括已删除):

    foreach (var entry in db3.ChangeTracker.Entries<TabModuleSetting>())
    {
        entry.State = System.Data.Entity.EntityState.Detached;
    }
    

    虽然通常您不必这样做。如果您想刷新实体,通常最好配置一个上下文并创建一个新上下文。

    【讨论】:

    • 那么,我如何强制进行数据库查找而不是缓存查找?或者,我如何清空缓存? .Clear 旨在清空结果集。在 .Find 语句之间发生了很多事情。
    • 添加了更多信息。
    • 好的。我认为处置和重新初始化 IMS 类会影响性能。第一次大约需要 15 秒。但是, db3.Dispose() db3=new IMS() 似乎不会导致性能问题,它可以处理我需要处理的问题。
    【解决方案2】:

    好的。我需要做的就是:

    db3.TabModuleSettings = new IMS().TabModuleSettings;

    就是这样。

    【讨论】:

    • 我想这就是我在回答的最后一行所说的。我还解释了你的第一种方法有什么问题。
    • 好吧。并不真地。您表示我应该处理整个上下文,丢失可能存在的任何其他实体。我仍然需要保留我以前的一些发现。我的方式,我只是处理一个选定的实体。 db3 是我的整个上下文,我不想丢失整个上下文。
    • 啊,那是你做的吗?我强烈建议不要这样做。您替换了整个 DbSet,而上下文的更改跟踪器仍包含前一组中实体的信息。这是一系列等待发生的奇怪错误。如果您删除选定的实体,您必须分离要删除的实体。在内部,EF 将保持其变更跟踪器(和关系管理器)同步。我修改了答案以包含该场景。
    • 哦,哇。好吧,我不知道。我认为重新初始化实体会清除该实体的更改跟踪器。更改跟踪器仅属于上下文而不属于实体。所以,你的第三种情况似乎是我需要的。使用 DbContext.SaveChanges() 更有意义。伟大的。我会试一试。
    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 2012-11-19
    • 2020-07-14
    • 1970-01-01
    相关资源
    最近更新 更多