entity frameworkcaching问题

我是entity framework的新手。

我已经在我的数据库中使用EF得到了一些值。 它完美地返回,值显示在标签中。 但是,当我删除我的表中的所有值(不使用EF),EF查询返回我的旧值。 我知道EF将这些值存储在caching中,并返回caching的数据以供后续运行。 它是否正确?

那么我怎样才能解决问题,当我已经删除了我的数据库中的所有值,但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(); } 

如果您知道EF以外发生了更改,并且想要刷新特定实体的ctxt,则可以调用ObjectContext.Refresh

 datamodel.Refresh(RefreshMode.StoreWins, orders); 

如果这看起来像是常见的事情,那么应该在查询中禁用对象caching:

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

或者为了closures特定实体的对象级caching,

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

在使用EF时,默认情况下,每个上下文只加载一次实体。 第一个查询创build实体实例并将其存储在内部。 后续任何需要具有相同键的实体的查询都将返回此存储的实例。 如果数据存储中的值发生更改,您仍然收到来自初始查询的值的实体

仔细的回答:

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

除非重新查询上下文,否则EF不会加载更改。 EF查询数据库和加载将其映射到对象中,它监视您在对象上执行的更改,而不是数据库上执行的更改。 EF不会跟踪直接对数据库所做的更改,也不会跟踪。

你已经加载了一个List,List是你在内存中的caching。 即使调用保存更改也不会刷新。 你将不得不再次查询上下文,这是创build新的列表。

要查看更改您将不得不再次执行以下行,

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

我想你应该在这里遵循一些其他的解决scheme,但似乎你想清除caching。 您可以通过执行以下操作来实现此目的:

 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 

下面的代码帮助我的对象刷新新的数据库值。 Entry(object).Reload()命令强制对象调用数据库值

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

我build议你在创build上下文之后使用一些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,我认为。

但是,你要清除“caching”的实体,把它分开。

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

Ctx是我的上下文。

首先,我不会build议修改系统外部的数据库,除非你只是在进行testing和开发。

EF DbContext包含一个IDisposable接口。 要释放任何caching的数据,请手动进行Dispose调用,或者将数据库对象放在使用块中。

  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(); } } 

这将确保上下文在下次使用时被清除并重新创build。 请务必为您的所有来电执行此操作,而不仅仅是您遇到的问题。

我怀疑这里的根本问题是你的DbContext挂了太久。 我可以从事实certificate你正在使用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); } } 

但是你真的应该看着dependency injection来pipe理DbContext生命周期

我认为你需要的是GetDatabaseValues() 。 它用于:

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

以下信息来自msdn :

当前值是实体当前包含的值。 原始值是查询实体时从数据库中读取的值。 数据库值是当前存储在数据库中的值。 自从查询实体以来,如果数据库中的值可能发生更改(例如,另一个用户对数据库进行并发编辑时),那么获取数据库值非常有用。

夫妇可以做的事情。

  1. 使用新的上下文。 caching的实体存储在上下文中。 使用新的上下文阻止它使用caching。
  2. 如果你真的想要一个全局/持久的上下文,你有两个子选项:a。)总是调用Reload方法。 db.Entry(entity).Reload()…这迫使上下文重新加载该实体。 b。)使用SqlDependency对象来检测logging何时更改和重新加载实体。 https://code.msdn.microsoft.com/How-to-use-SqlDependency-5c0da0b3