实体框架缓存问题(Entity Framework Caching Issue)

2019-08-19 18:00发布

我是新来的实体框架。

我必须去使用EF在我的数据库中的值。 它返回完美,和值在标签所示。 但是当我在我的表中删除所有值(不使用EF),将EF查询返回我的旧值。 我知道EF存储在缓存中的值,并返回后续运行缓存的数据。 它是否正确?

那么,如何解决,当我在我的数据库中删除了所有值的问题,但EF返回旧值?

编辑

现在我用datamodel.SaveChanges() 但现在还它返回相同的旧值。

我的示例查询看起来象下面这样:

SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities();
datamodel.SaveChanges();
List<Compliance> compliance=new List<Compliance>();
IList<ComplianceModel> complianceModel;
if (HttpContext.Current.User.IsInRole("SuperAdmin"))
{
    compliance = datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList();
}

Answer 1:

如果你知道发生了变化EF之外,并希望刷新ctxt特定的实体,您可以拨打ObjectContext.Refresh

datamodel.Refresh(RefreshMode.StoreWins, orders);

如果这似乎是这将是一个普遍的现象,应禁用对象缓存在查询:

SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities();
datamodel.tblCities.MergeOption = MergeOption.NoTracking; 

或关闭对象级缓存特定实体,

Context.Set<Compliances>().AsNoTracking();


Answer 2:

当您使用默认加载的EF它的每个实体只有一次,每个上下文。 第一个查询创建实体instace并在内部存储。 任何后续查询需要使用相同的密钥将返回此存储的实例实体。 如果数据存储值改变了你仍然收到实体从初始查询值

细心的回答:

https://stackoverflow.com/a/3653392/1863179



Answer 3:

除非你重新查询上下文EF不会加载的变化。 EF查询数据库,并加载它们映射到对象,它看着你的对象,而不是对数据库执行的变化。 EF不跟踪直接向数据库的变化和它永远不会跟踪。

您装入的名单,这名单是你在内存中缓存。 即使调用保存更改不会刷新。 你将不得不再次查询的背景下,这是创建新的列表。

要看到改变,你必须执行以下行一次,

datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList()


Answer 4:

我想你应该遵循一些其他的解决方案在这里,但它似乎像你想清除缓存。 您可以通过执行以下步骤实现:

var count = datamodel.Compliances.Local.Count; // number of items in cache (ex. 30)

datamodel.Compliances.Local.ToList().ForEach(c => {
    datamodel.Entry(c).State = EntityState.Detached;
});

count = datamodel.Compliances.Local.Count; // 0


Answer 5:

下面的代码帮助我的对象,与新鲜的数据库值被刷新。 该条目(对象).Reload()命令强制召回数据库值对象

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();


Answer 6:

我建议你使用一些MergeOption所有EntitieSet创建后的背景下,这样的:

var objSetProps = ctx.GetType().GetProperties().Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(ObjectSet<>));
foreach (PropertyInfo objSetProp in objSetProps)
{
    ObjectQuery objSet = (ObjectQuery)objSetProp.GetValue(ctx, BindingFlags.GetProperty, null, null, null);
    objSet.MergeOption = MergeOption.PreserveChanges;
}

阅读关于MergeOption这里: http://msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx你会用NoTracking,我想。

但是,IY你whant清除“缓存”的实体,它分离。

var entidades = Ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged);
foreach (var objectStateEntry in entidades)
    Ctx.Detach(objectStateEntry.Entity);

凡CTX是我的上下文。



Answer 7:

首先,我不会建议修改数据库外部到你的系统,除非你只是做测试和开发。

EF英孚的DbContext包含IDisposable接口。 要释放所有缓存数据或者使处置手动呼叫或将您的数据库对象使用一个块中。

        using (SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities())
        {
            List<Compliance> compliance = new List<Compliance>();
            IList<ComplianceModel> complianceModel;
            if (HttpContext.Current.User.IsInRole("SuperAdmin"))
            {
                compliance = datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList();
            }
        }

这将确保上下文被清除,并重新使用它的下一次。 确保为所有来电,而不只是你遇到问题的一个做到这一点。



Answer 8:

我怀疑这里的根本问题是,你DbContext过长游逛。 我可以说你正在使用的事实告诉HttpContext ,你有一个Web应用程序,并用的DbContext工作时的一般准则包括:

当使用Web应用程序,使用每个请求的上下文实例。

如果您正在使用MVC,你可以在你的控制器这样使用Dispose模式:

public class EmployeeController : Controller
{
    private EmployeeContext _context;

    public EmployeeController()
    {
        _context = new EmployeeContext();
    }

    public ActionResult Index()
    {
        return View(_context.Employees.ToList());
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _context.Dispose();
        }
        base.Dispose(disposing);
    }
}

但是,你真的应该寻找在依赖注入管理的DbContext寿命



Answer 9:

我想你需要的是GetDatabaseValues() 它用于这样的:

context.Entry(/*your entry*/).GetDatabaseValues();

以下信息是从MSDN :

当前值是实体的性质目前包含的值。 原始值是从数据库中读取的实体进行查询时的值。 因为他们目前存储在数据库中的数据库值的值。 获取数据库值是有用的,当在数据库中的值可能已经改变,因为实体被查询时并发编辑到数据库已被其他用户做出如。



Answer 10:

夫妇的事情可以做。

  1. 使用新的上下文。 缓存的实体存储在上下文。 使用新的上下文阻止它使用缓存。
  2. 如果你真的想要一个全球性的/持久的背景下,你有两个子选项:a。)始终调用Reload方法。 db.Entry(实体).Reload()...这个强制执行上下文来重新加载实体。 湾)使用的SqlDependency对象检测何时记录改变,并根据需要重新加载的实体。 https://code.msdn.microsoft.com/How-to-use-SqlDependency-5c0da0b3


Answer 11:

就我而言,这是一个糟糕的连接字符串。 实体看上去就像是做的很好,因为它从来没有抱怨过,直到我的上下文本地和它终于给我的错误信息。



文章来源: Entity Framework Caching Issue