Problème de mise en cache dans Entity Framework

Je suis nouveau sur Entity Framework.

J’ai obtenu des valeurs dans ma firebase database en utilisant EF. Il retourne parfaitement et les valeurs sont affichées sous forme d’étiquettes. Mais lorsque je supprime toutes les valeurs de ma table (sans utiliser EF), la requête EF renvoie mes anciennes valeurs. Je sais que l’EF stocke les valeurs dans le cache et renvoie les données mises en cache pour les exécutions suivantes. Est-ce correct?

Alors, comment puis-je résoudre le problème lorsque j’ai supprimé toutes les valeurs de ma firebase database, mais que EF renvoie les anciennes valeurs?

Modifier :

Maintenant, j’ai utilisé datamodel.SaveChanges() . Mais maintenant, il retourne les mêmes valeurs anciennes.

Mon exemple de requête est le suivant:

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

Si vous savez que des modifications ont eu lieu en dehors d’EF et que vous souhaitez actualiser votre ctxt pour une entité spécifique, vous pouvez appeler ObjectContext.Refresh.

 datamodel.Refresh(RefreshMode.StoreWins, orders); 

Si cela semble être un phénomène courant, vous devez désactiver la mise en cache des objects dans vos requêtes:

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

ou pour désactiver la mise en cache de niveau object pour une entité spécifique,

 Context.Set().AsNoTracking(); 

Lorsque vous utilisez EF, il charge par défaut chaque entité une seule fois par contexte. La première requête crée une instance d’entité et la stocke en interne. Toute requête ultérieure qui requirejs une entité avec la même clé renvoie cette instance stockée. Si les valeurs du magasin de données ont changé, vous recevez toujours l’entité avec les valeurs de la requête initiale

Une réponse prudente:

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

EF ne chargera les modifications que si vous interrogez le contexte. EF interroge db et les charge en objects, il surveille les modifications que vous effectuez sur les objects et non sur la firebase database. EF ne suit pas les modifications apscopes directement à la firebase database et ne suivra jamais.

Vous avez chargé une liste, cette liste est votre cache en mémoire. Même appeler Enregistrer les modifications ne sera pas actualisé. Vous devrez à nouveau interroger le contexte, c’est-à-dire créer une nouvelle liste.

Pour voir les modifications Vous devrez exécuter la ligne suivante une fois de plus,

 datamodel.Compliances.Where(c => c.School.DissortingctId == dissortingctId).ToList() 

Je pense que vous devriez suivre certaines des autres solutions ici, mais il semble que vous vouliez vider le cache. Vous pouvez y parvenir en procédant comme suit:

 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 

Le code ci-dessous a aidé mon object à être actualisé avec de nouvelles valeurs de firebase database. La commande Entry (object) .Reload () force l’object à rappeler les valeurs de la firebase database

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

Je vous recommande d’utiliser certains MergeOption à tous les EntitieSet après créer le contexte, comme ceci:

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

Lisez à propos de MergeOption ici: http://msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx Vous allez utiliser NoTracking, je pense.

Mais, vous pouvez effacer les entités “en cache”, en les détachant.

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

Où Ctx sont mon contexte.

Tout d’abord, je ne suggère pas de modifier la firebase database externe à votre système, sauf si vous ne faites que des tests et du développement.

Le EF DbContext contient une interface IDisposable. Pour libérer des données en cache, effectuez manuellement les appels Dispose ou placez votre object Database dans un bloc using.

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

Cela assurera que le contexte est effacé et recréé la prochaine fois qu’il est utilisé. Assurez-vous de le faire pour tous vos appels et pas seulement celui avec lequel vous rencontrez des problèmes.

Je soupçonne que le problème sous-jacent ici est que votre DbContext traîne trop longtemps. Je peux dire par le fait que vous utilisez HttpContext que vous avez une application Web et que les instructions générales pour travailler avec DbContext incluent

Lorsque vous travaillez avec des applications Web, utilisez une instance de contexte par demande.

Si vous utilisez MVC, vous pouvez utiliser le modèle Dispose dans votre contrôleur comme suit:

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

Mais vous devriez vraiment regarder l’dependency injection pour gérer la durée de vie de DbContext

Je pense que vous avez besoin de GetDatabaseValues() . Il est utilisé comme:

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

L’information ci-dessous est de msdn :

Les valeurs actuelles sont les valeurs que les propriétés de l’entité contiennent actuellement. Les valeurs d’origine sont les valeurs lues dans la firebase database lorsque l’entité a été interrogée. Les valeurs de firebase database sont les valeurs telles qu’elles sont actuellement stockées dans la firebase database. Obtenir les valeurs de la firebase database est utile lorsque les valeurs de la firebase database ont changé depuis la requête de l’entité, par exemple lorsqu’un autre utilisateur a effectué une modification simultanée de la firebase database.

Couple de choses que vous pouvez faire.

  1. Utilisez un nouveau contexte. Les entités mises en cache sont stockées dans le contexte. L’utilisation d’un nouveau contexte l’empêche d’utiliser le cache.
  2. Si vous voulez vraiment un contexte global / durable, vous avez deux sous-options: a.) Appelez toujours la méthode Reload. db.Entry (entity) .Reload () … force le contexte à recharger cette entité. b.) utiliser un object SqlDependency pour détecter le moment où les enregistrements changent et recharger les entités selon les besoins. https://code.msdn.microsoft.com/How-to-use-SqlDependency-5c0da0b3