Question

J'ai eu quelques problèmes avec LINQ-To-SQL concernant l'utilisation de la mémoire. Je l'utilise dans un service Windows pour effectuer certains traitements, et je parcours une grande quantité de données que je retire du contexte. Oui, je sais que je pourrais le faire avec une procédure stockée, mais il y a des raisons pour lesquelles ce serait une solution moins qu'idéale.

Quoi qu'il en soit, ce que je vois en gros, c’est que la mémoire n’est pas libérée même après avoir appelé context.SubmitChanges () . Je finis donc par faire toutes sortes de choses étranges, comme ne récupérer que 100 enregistrements à la fois, ou créer plusieurs contextes et les faire effectuer des tâches distinctes. Si je conserve le même DataContext et que je l’utilise plus tard pour d’autres appels, il ne fait que consommer de plus en plus de mémoire. Même si j'appelle Clear () sur le " var tableRows " tableau que la requête me renvoie, définissez-la sur null et appelez SYstem.GC.Collect () - la mémoire n'est toujours pas libérée.

Maintenant, j'ai lu quelques explications sur la façon dont vous devriez utiliser DataContexts rapidement et en disposer rapidement, mais il semble que leur devrait être un moyen de forcer le contexte à vider toutes ses données (ou toutes ses données de suivi pour une table particulière) à un moment donné pour garantir la mémoire est libre.

Quelqu'un sait-il quelles étapes garantissent la libération de la mémoire?

Était-ce utile?

La solution

Si vous n'avez pas besoin du suivi des objets, définissez DataContext.ObjectTrackingEnabled sur false . Si vous en avez besoin, vous pouvez utiliser la réflexion pour appeler le DataContext.ClearCache () interne, même si vous devez savoir que, depuis son interne, il est susceptible de disparaître dans une future version du cadre. Et pour autant que je sache, le framework lui-même ne l'utilise pas, mais il efface le cache d'objets.

Autres conseils

Un DataContext suit tous les objets qu'il a jamais récupérés. Il ne le libérera pas tant que les ordures ne seront pas ramassées. De plus, comme il implémente IDisposable , vous devez appeler Dispose ou utiliser l'instruction à l'aide de .

C’est la bonne façon de faire:

using(DataContext myDC = new DataContext)
{
  //  Do stuff
} //DataContext is disposed

Comme le fait remarquer David, vous devez vous débarrasser du DataContext en utilisant un bloc using.

Il semble que votre principale préoccupation concerne la création et la suppression d'un groupe d'objets DataContext. C’est ainsi que linq2sql est conçu. Le DataContext est censé avoir une durée de vie courte. Étant donné que vous extrayez beaucoup de données de la base de données, il est logique d’utiliser beaucoup de mémoire. Vous êtes sur la bonne voie en traitant vos données en morceaux.

N'ayez pas peur de créer une tonne de DataContexts. Ils sont conçus pour être utilisés de cette façon.

Merci les gars - je vais vérifier la méthode ClearCache. Juste pour clarifier (pour les futurs lecteurs), la situation dans laquelle je me servais de mémoire ressemblait à ceci:

using(DataContext context = new DataContext())
{
   while(true)
   {
      int skipAmount = 0;
      var rows = context.tables.Select(x => x.Dept == "Dept").Skip(skipAmount).Take(100);

      //break out of loop when out of rows

      foreach(table t in rows)
      {
         //make changes to t   
      }

      context.SubmitChanges();
      skipAmount += rows.Count();

      rows.Clear();
      rows = null;

      //at this point, even though the rows have been cleared and changes have been
      //submitted, the context is still holding onto a reference somewhere to the
      //removed rows.  So unless you create a new context, memory usuage keeps on growing
   }
}

Je viens de rencontrer un problème similaire. Dans mon cas, j'ai aidé à définir les propriétés de DataContext.ObjectTrackingEnabled sur false. Mais cela ne fonctionne que dans le cas de parcourir les lignes comme suit:

using (var db = new DataContext())
{
    db.ObjectTrackingEnabled = false;
    var documents = from d in db.GetTable<T>()
                     select d;
    foreach (var doc in documents)
    {
        ...
    }
}

Si, par exemple, dans la requête, utilisez les méthodes ToArray () ou ToList () - aucun effet

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top