Linq to SQL DataContext проблема утечки памяти Windsor IoC

У меня есть приложение ASP.NET MVC, которое создает текст данных Linq2SQL для каждого веб-запроса с использованием Castler Windsor IoC.

По какой-то причине, которую я не полностью понимаю, каждый раз, когда создается новый текст данных (при каждом веб-запросе), около 8 КБ памяти занимают и не освобождают, что неизбежно вызывает исключение OutOfMemory.

Если я принудительно выполняю сборку мусора, память освобождается нормально.

Мой класс datacontext очень прост:

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

Веб-конфигурация Windsor IoC для создания этого экземпляра выглядит так:

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

Кто-нибудь знает, в чем проблема, и как ее исправить?


person Mr. Flibble    schedule 10.11.2009    source источник
comment
См .: stackoverflow.com/questions/85183/ stackoverflow.com/questions/132940/   -  person Mauricio Scheffer    schedule 11.11.2009


Ответы (4)


L2S DataContext реализует IDisposable. Ваш интерфейс также должен реализовать это и вызвать DataContext.Dispose (), чтобы Виндзор знал, что есть ресурсы, которые нужно удалить.

Кстати, остерегайтесь проблем Windsor / IDisposable: http://www.jeremyskinner.co.uk/2008/05/03/aspnet-mvc-controllers-windsor-and-idisposable/ http://www.nablasoft.com/Alkampfer/?p=105

person queen3    schedule 10.11.2009

Нет ваш DataContextAccessor не нужно реализовывать IDisposable. Виндзор достаточно умен, чтобы справиться с этим случаем, не внося никаких изменений в ваши классы.

Однако, поскольку, как отмечено в других ответах, DataContext реализует его, и Виндзор видит его и регистрирует его для очистки (для вызова на нем метода Dispose).

Что вам нужно сделать, так это вызвать container.Release и передать вашу корневую службу (что, вероятно, будет DataContextAccessor в вашем случае). Затем Windsor освободит его и все его зависимости (он также вызовет Dispose на DataContext), и память будет освобождена.

Если вы используете ASP.NET MVC, подумайте об использовании проекта MVCContrib, в котором есть интеграция с Windsor, которая обрабатывает выпуск компонентов за вас.

person Krzysztof Kozmic    schedule 18.05.2010

Насколько я могу судить, queen3 правильно, ваш DataContextAccessor класс должен реализовать IDisposable и вызвать datacontext.Dispose() из своего .Dispose() метода. (Отказ от ответственности: я не работал с Castle Windsor.)

В качестве альтернативы я бы превратил ваш DataContextAccessor в DataContextFactory, который создает DataContext только при вызове метода (например, GetContext()). Тогда вы можете сделать это:

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

Вы также можете взглянуть на этот предыдущий вопрос: Как согласовать IDisposable и IoC?

person Daniel Pryden    schedule 10.11.2009

Я думаю, что @Krzysztof Koźmic прав ... ты должен выпустить все, что получишь от Виндзора.

Виндзор довольно чужд для всех, кто привык к IDisposable. Причина этого очевидного несоответствия кроется в управлении жизненным циклом компонента. Если вы возьмете компонент из Виндзора, который является IDisposable, вы не знаете, настроен ли этот экземпляр как временный или одноэлементный (и, конечно, это может измениться по мере развития вашего приложения).

Если вы удалите компонент, и он позже окажется синглтоном, какой-то другой клиентский код задастся вопросом, почему его компонент внезапно вышел из строя!?! Только Виндзор может принять решение об утилизации за вас.

Хорошая запись в блоге, Кшиштоф (не позволю мне публиковать ссылку!)

В нашем приложении мы сделали все временным, кроме пары синглтонов. Transient кажется самой простой моделью (если все понимают, что нужно «Освободить, а не утилизировать»). Если у вас есть фиктивный контейнер в ваших тестах, вы можете установить ожидание, что Release будет вызываться для каждого компонента, который разрешает ваш макет, и я также слышал, что у переходного процесса меньше проблем с производительностью (??), чем у других режимов? Код, безусловно, более переносимый.

И последнее, но не менее важное: если у вас есть утечка памяти и вам нужно разобраться, что и почему что-то не собирается сборщиком мусора, посмотрите серию потрясающих руководств Тесс Феррандес на windbg http://blogs.msdn.com/b/tess/archive/2008/04/03/net-debugging-demos-lab-7-memory-leak-review.aspx ... виноват может быть где-то неожиданно!

person kenno    schedule 13.10.2010