实体框架缓存问题

Ram*_*ran 51 c# asp.net-mvc entity-framework catch-all

我是Entity Framework的新手.

我使用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();
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ich 38

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

datamodel.Refresh(RefreshMode.StoreWins, orders);
Run Code Online (Sandbox Code Playgroud)

如果这似乎是常见的事情,您应该在查询中禁用对象缓存:

SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities();
datamodel.tblCities.MergeOption = MergeOption.NoTracking; 
Run Code Online (Sandbox Code Playgroud)

或者为了关闭特定实体的对象级缓存,

Context.Set<Compliances>().AsNoTracking();
Run Code Online (Sandbox Code Playgroud)

  • 如果使用AsNoTracking(),则DBContext将不跟踪对Enetities的更改.在这种情况下,您将无法使用dbContext.SaveChanges()修改实体并保存它们. (5认同)
  • .AsNoTracking()对我来说 (4认同)
  • @零3。这就有点矛盾了。一旦你说“你只需要……”,你就创造了一个例外情况。阿比吉特说的是对的。当您使用 AsNoTracking 时,您正在加载一个实体,而无需在更改跟踪器中注册它。SaveChanges 不会保存对实体的修改。如果您想保存对实体实例的更改,您需要通过调用 Attach 手动将实体添加到上下文的更改跟踪器来撤消您的 AsNoTracking。只有在这样做之后,对实体的更改才会通过 SaveChanges 保存。 (2认同)

Mor*_*eza 28

当您使用EF时,默认情况下,每个上下文仅加载一个实体.第一个查询创建实体实例并在内部存储它.任何需要具有相同键的实体的后续查询都会返回此存储的实例.如果数据存储中的值发生更改,您仍会收到包含初始查询值的实体

仔细回答:

/sf/answers/255737471/

  • 简短版:"绝不使用全球背景" (13认同)
  • 我一直在疯狂地调试,进入SSMS并检查我能找到的原因为什么某些电话没有被更新......现在我知道了!谢谢! (2认同)

Aka*_*ava 20

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

您已加载List,List是您在内存中的缓存.即使调用Save Changes也不会刷新.您将不得不再次查询上下文,即创建新列表.

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

datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList()
Run Code Online (Sandbox Code Playgroud)


Dav*_*ret 7

我认为你应该遵循其他一些解决方案,但似乎你想要清除缓存.您可以通过执行以下操作来实现此目的:

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
Run Code Online (Sandbox Code Playgroud)


Tia*_*vêa 5

我建议您在创建上下文后对所有 EntitieSet 使用一些 MergeOption,如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)

在此处阅读有关 MergeOption 的信息:http : //msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx 我认为您将使用 NoTracking。

如果要清除“缓存”实体,请将其分离。

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

Ctx 是我的上下文。