4

J'ai une application ASP.NET MVC qui crée une datacontext Linq2SQL sur une base de demande par Internet en utilisant Castler Windsor IoC.Linq à un problème de fuite de mémoire SQL DataContext Windsor IoC

Pour une raison que je ne comprends pas complètement, chaque fois qu'un nouveau datacontext est créé (sur chaque requête web), environ 8k de mémoire sont repris et non libérés - ce qui provoque inévitablement une exception OutOfMemory.

Si je force la collecte des ordures la mémoire est libérée OK.

Ma classe DataContext est très simple:

public class DataContextAccessor : IDataContextAccessor 
{ 
    private readonly DataContext dataContext; 
    public DataContextAccessor(string connectionString) 
    { 
     dataContext = new DataContext(connectionString);   
    } 
    public DataContext DataContext { get { return dataContext; } } 
} 

Le Windsor IoC webconfig à instancier cela ressemble à ceci:

<component id="DataContextAccessor" 
      service="DomainModel.Repositories.IDataContextAccessor, DomainModel" 
      type="DomainModel.Repositories.DataContextAccessor, DomainModel" 
      lifestyle="PerWebRequest">  
    <parameters> 
     <connectionString> 
     ... 
     </connectionString> 
    </parameters> 
    </component> 

Est-ce que quelqu'un sait quel est le problème et comment le résoudre?

+1

Voir: http://stackoverflow.com/questions/85183/windsor-container-how-to-force-dispose-of-an-object http://stackoverflow.com/questions/132940/why-does- castle-windsor-hold-on-transitoire-objets –

Répondre

3

D'après ce que je peux dire, queen3 est correct, votre DataContextAccessor classe a besoin de mettre en œuvre IDisposable et appeler datacontext.Dispose() de sa méthode .Dispose(). (Avertissement: Je ne l'ai pas travaillé avec le château de Windsor.)

Sinon, ce que je ferais est de transformer votre DataContextAccessor en DataContextFactory, qui ne crée que l'DataContext lorsque vous appelez une méthode (par exemple GetContext()). Ensuite, vous pouvez faire ceci:

using(DataContext context = myDataContextFactory.GetContext()) { 
    // Do whatever you want with the context 
} 
// Context is disposed here 

Vous pouvez également jeter un oeil à cette question précédente: How do you reconcile IDisposable and IoC?

4

Pas votre DataContextAccessor n'a pas besoin de mettre en œuvre IDisposable. Windsor est assez intelligent pour gérer l'affaire sans avoir à apporter de modifications à vos cours.

Cependant, comme indiqué dans les autres réponses, DataContext l'implémente, et Windsor le voit et l'enregistre pour le nettoyage (pour appeler la méthode Dispose).

Ce que vous devez faire est d'appeler container.Release et passer votre service racine (qui serait probablement DataContextAccessor dans votre cas). Windsor va alors le libérer et toutes ses dépendances (il appellera aussi Dispose sur DataContext) et la mémoire sera libérée.

Si vous utilisez ASP.NET MVC envisager d'utiliser projet MvcContrib qui a l'intégration de Windsor qui gère la libération de composants pour vous.

1

Je pense @Krzysztof Kozmic est juste ... vous devez libérer tout ce que vous obtenez de Windsor.

Windsor est assez étranger à personne utilisé pour IDisposable. La raison de cette apparente disparité est liée à la gestion du cycle de vie du composant.Si vous prenez un composant de Windsor qui est IDisposable, vous ne savez pas si cette instance est configurée comme transitoire ou singleton (et bien sûr cela pourrait changer au fur et à mesure que votre application évolue).

Si vous disposez d'un composant et qu'il s'avère plus tard être un singleton, un autre code client va se demander pourquoi son composant a soudainement échoué!?! Seul Windsor est en mesure de prendre la décision d'élimination pour vous.

blog de Nice Krzysztof (ne me laisse poster le lien!)

Dans notre application, nous avons fait tout transitoire, à part quelques singletons. Le transitoire semble être le modèle le plus simple (à condition que tout le monde comprenne que vous devez «relâcher plutôt que détruire»). Si vous avez un conteneur fictif dans vos tests, vous pouvez définir une attente que Release est appelée pour chaque composant que votre maquette résout, et j'ai également entendu dire que transitoire a moins de problèmes de performance (??) que d'autres modes? Le code est certainement plus portable.

Last but not least, si vous avez une fuite de mémoire et vous avez besoin de travailler ce et pourquoi quelque chose ne sont pas recueillies par le GC, consultez la série tutoriel fab « Tess Ferrandez sur WinDBg http://blogs.msdn.com/b/tess/archive/2008/04/03/net-debugging-demos-lab-7-memory-leak-review.aspx ... le coupable peut être quelque part inattendu!