Je vois qu’il y a beaucoup de questions sur le cache EF, mais je n’ai pas encore trouvé de solution à mon problème.
Comment désactiver complètement le cache Entity Framework 6? Ou, puis-je demander par programme à EF d’oublier le cache, car quelque chose est arrivé aux données?
Premièrement, j’ai hérité d’ une application faite d’un mélange étrange de EF (modèle-premier pour définir des entités) et plaine vieux SQL (pour manipuler des données). Ce que j’ai fait, c’est de refactoriser l’application pour:
GetAll()
pour une entité) utiliser EF6 LINQ DbContext.Database.Connection
cas de besoin Spring.Web
support Spring.Web
pour activer DI et les transactions (pas encore) À ce stade, j’ai réorganisé le code de sorte que la fonction principale de l’application (exécuter des requêtes SQL complexes sur des jeux de données volumineux) fonctionne comme auparavant, mais la manipulation des entités de domaine de recherche est ensuite effectuée plus intelligemment en utilisant le plus possible Entity Framework.
Une des pages dont j’ai hérité est une page à coches multiples que je vais vous montrer pour une meilleure compréhension. Je ne discuterai pas du choix de l’ancien implémenteur, car il est moins coûteux de résoudre mon problème actuel et de modifier plus tard le code de refactorisation plutôt que de bloquer le développement d’une fonctionnalité défectueuse.
Voici à quoi ressemble la page
Fondamentalement, la méthode du Controller
est la suivante
[HttpPost] public ActionResult Index(ssortingng[] codice, ssortingng[] flagpf, ssortingng[] flagpg, ssortingng[] flagammbce, ssortingng[] flagammdiv, ssortingng[] flagammest, ssortingng[] flagintab, ssortingng[] flagfinanz, ssortingng[] flagita, ssortingng[] flagest, ssortingng pNew){ Sottogruppo2015Manager.ActivateFlagFor("pf", flagpf); Sottogruppo2015Manager.ActivateFlagFor("pg", flagpg); Sottogruppo2015Manager.ActivateFlagFor("ammbce", flagammbce); Sottogruppo2015Manager.ActivateFlagFor("ammdiv", flagammdiv); Sottogruppo2015Manager.ActivateFlagFor("ammest", flagammest); Sottogruppo2015Manager.ActivateFlagFor("intab", flagintab); Sottogruppo2015Manager.ActivateFlagFor("finanz", flagfinanz); Sottogruppo2015Manager.ActivateFlagFor("ita", flagita); Sottogruppo2015Manager.ActivateFlagFor("est", flagest); return RedirectToAction("Index", new { pNew }); }
Chaque paramètre ssortingng[]
est une colonne de la table. La méthode ActivateFlagFor
exécute deux requêtes en séquence
UPDATE table SET --param1-- = 0; UPDATE table SET --param1-- = 1 where id in (--param2--)
Ce qui suit est le comportement:
Je suis sûr qu’il s’agit d’un problème de mise en cache, car le rechargement de l’application corrige le problème. Étant donné que la fonctionnalité principale de l’application est entièrement basée sur SQL, les modifications apscopes aux tables de recherche sont reflétées dans l’opération principale et constituent le comportement correct.
Je comprends que la mise en cache EF est une fonctionnalité intéressante pour les performances, mais dans mon cas, je ne la souhaite tout simplement pas, du moins tant que je n’ai pas migré l’ensemble de l’application vers LINQ DML (probablement impossible).
DbContext
Bien sûr, certains d’entre vous peuvent demander “comment utilisez-vous votre DbContext?” “en disposez-vous correctement?”
IManager
étendant BaseManager
DbContext
est un object Spring DbContext
une requête. J’ai déjà posé une question sur la disposition des objects liés à la requête, mais j’ai actuellement implémenté une solution de contournement qui, bien que mauvaise, supprime correctement le DbContext à la fin de la demande. public class ExampleManagerImpl : BaseManager, IExampleManager { public void ActivateFlagFor(ssortingng aFlag, ssortingng[] aList) { ssortingng sql = "UPDATE table SET flag" + aFlag + " = 0"; RunStatementV1(sql); if (aList != null && aList.Any()) { sql = "UPDATE table SET flag" + aFlag + " = 1 WHERE id in (" + aList.ToCsvApex() + ")"; RunStatementV1(sql); } } public IList GetAll() { return DataContext.example.ToList(); //I don't dispose of the DataContext willingly } }
et
public abstract class BaseManager { public DbContext DataContext { get; set; } //Autowired protected void RunStatementV1(ssortingng aSqlStatement) { IDbConnection connection = DataContext.Database.Connection; if (connection.State == ConnectionState.Closed || connection.State == ConnectionState.Broken) connection.Open(); //Needed because sometimes I found the connection closed, even if I don't dispose of it using (IDbCommand command = connection.CreateCommand()) { command.CommandText = aSqlStatement; command.ExecuteNonQuery(); } } }
Detach
semble résoudre le problème, mais il faudrait que je l’applique à une douzaine d’entités pour pouvoir revenir un jour plus tard. Si vous souhaitez ignorer complètement le cache de EF6 pour la récupération de données, ajoutez AsNoTracking()
à la fin de votre requête (avant d’appeler ToList()
ou de faire autre chose qui l’exécuterait.
MSDN sur AsNoTracking()
Veuillez noter que cela ne vérifiera pas le cache pour les données existantes, ni n’appenda les résultats de l’appel de la firebase database au cache. En outre, Entity Framework ne détectera pas automatiquement les modifications apscopes aux entités extraites de la firebase database. Si vous souhaitez modifier des entités et les enregistrer dans la firebase database, vous devez attacher les entités modifiées avant d’appeler SaveChanges()
.
Votre méthode est actuellement:
public IList GetAll() { return DataContext.example.ToList(); }
Cela changerait à:
public IList GetAll() { return DataContext.example.AsNoTracking().ToList(); }
Si vous êtes intéressé par d’autres options pour traiter le cache d’EF, j’ai écrit un article de blog sur EF6 Cache Busting .
J’ai eu ce problème aussi, mais je pouvais le réparer.
J’utilise le modèle de référentiel et j’utilise le DI par défaut de .Net Core. J’utilise AddSingleton (…), mais c’est mal d’utiliser avec DbContext.
J’ai donc changé pour AddScoped, comme je l’ai lu dans docs: Les services de durée de vie Scoped sont créés une fois par demande.
Cela a résolu mon problème.
Vous devez lire cette section à partir de ms docs: Durée de vie du service et options d’enregistrement